Jump To …

trippleyatch.coffee

@copy 2012 - Thom Porter (www.thomporter.com)

base rule class for other rules to extend

class Rule

  constructor: (parent) ->
    @_ = parent

    @onval = 0;
    @el = $('<div class="rule clearfix"></div>')
    if (@ instanceof NumRule)
      @el.appendTo(@_.rulesv)
    else
      @el.appendTo(@_.rules2v)

    @ruletext = $('<div class="ruletext"></div>').appendTo(@el)

    @vals = [-1,-1,-1]

    @val_views = [
      $('<div class="ascore scoreable">-</div>').appendTo(@el),
      $('<div class="ascore">-</div>').appendTo(@el),
      $('<div class="ascore">-</div>').appendTo(@el)
    ]

    @val_views[0].on('click', @valclick)

  valclick: =>
    return unless @_.canScore

    @val_views[@onval].removeClass('scoreable').off('click')
    s = @getDiceScore()
    @vals[@onval] = s
    @_.addToScore(s)

    @onval++
    if (@onval < 3)
      @val_views[@onval].addClass('scoreable').on('click',@valclick)

    @_.nextTurn()
    @_.roll()


  getRuleScore: ->
    t = 0
    t += @vals[0] unless @vals[0] == -1
    t += @vals[1] unless @vals[1] == -1
    t += @vals[2] unless @vals[2] == -1
    t

  checkScore: ->
    @val_views[@onval]?.text(@getDiceScore())


  getDiceScore: ->
    0


  total: ->
    t = 0
    t += @val1 unless @val1 == -1
    t += @val2 unless @val2 == -1
    t += @val3 unless @val3 == -1
    t

  getNumEqualTo: (i) ->
    numEqual = 0
    numEqual++ unless @_.d1.num != i
    numEqual++ unless @_.d2.num != i
    numEqual++ unless @_.d3.num != i
    numEqual++ unless @_.d4.num != i
    numEqual++ unless @_.d5.num != i
    numEqual

Class to handle rules for individual numbers

class NumRule extends Rule

  constructor: (parent) ->
    super
    @num = 0

  setNum: (i) ->
    @num = i
    @ruletext.text(i + 's')
    @

  getDiceScore: ->
    s = 0
    s += @num unless @_.d1.num != @num
    s += @num unless @_.d2.num != @num
    s += @num unless @_.d3.num != @num
    s += @num unless @_.d4.num != @num
    s += @num unless @_.d5.num != @num
    s

Class to handle 3 & 4 of a kind rules

class ofAKindRule extends Rule

  constructor: (parent) ->
    super
    @ofhowmany = 0

  setNum: (i) ->
    @ofhowmany = i
    @ruletext.text(i + ' of a kind')
    @

  getDiceScore: ->
    s = 0

    for i in [6..1] by -1
      numEqual = @getNumEqualTo(i)
      if (numEqual >= @ofhowmany)
        return @_.getDieTotal()
    0

Class to handle 5 of a kind (aka the Yatch)

class yatchRule extends Rule

  constructor: (parent) ->
    super
    @ruletext.text('The Yatch!')

  getDiceScore: ->
    if (@_.d1.num == @_.d2.num == @_.d3.num == @_.d4.num == @_.d5.num)
      return 100
    0

Class to handle a full house

class fullBoatRule extends Rule

  constructor: (parent) ->
    super
    @ruletext.text('Full Boat')

  getDiceScore: ->
    havePair = false
    haveThreeOfAKind = false


    for i in [6..1] by -1
      numEqual = @getNumEqualTo(i)
      if (numEqual == 2)
        havePair = true
      else if (numEqual == 3)
        haveThreeOfAKind = true
      else if (numEqual == 5)
          havePair = haveThreeOfAKind = true
    if (havePair && haveThreeOfAKind)
      return 35

    0

Class to handle the chance spaces

class chanceRule extends Rule

  constructor: (parent) ->
    super
    @ruletext.text('Chance')

  getDiceScore: ->
    @_.getDieTotal()

Class to handle the small & large straights

class inARowRule extends Rule

  constructor: (parent) ->
    super
    @len = 0
    @val = 0

  setLen: (len) ->
    @len = len
    if len == 4
      @ruletext.text('Small Straight')
    else
      @ruletext.text('Big Straight')
    @

  setVal: (val) ->
    @val = val
    @

  getDiceScore: ->
    score = 0

    vals = [
      @_.d1.num,
      @_.d2.num,
      @_.d3.num,
      @_.d4.num,
      @_.d5.num
    ]
    vals.sort()


    uniqueVals = []

    for v in vals
      if ($.inArray(v, uniqueVals) == -1)
        uniqueVals.push(v)

    last_v = uniqueVals.shift()
    c = 1
    for v in uniqueVals
      if last_v + 1 == v
        c++
      else if (c < 4)
        c = 1
      last_v = v
    if c >= @len
      score = @val

    score

the main game class

class TrippleYatch extends Game

  constructor: () ->
    @name = 'Tripple Yatch!'
    @game_key = 'trippleyatch'
    super
    @snd =
      roll: new Audio('/lib/games/snd/diceshake.mp3')
    @snd.roll.volume = 0.25
    @rollCount = 0
    @instantRoll = false
    @bonus_at = 192
    @bonus_val = 105
    @bonus = 0
    @ruleCount = 39
    @canScore = false
    @rolling = 0
    @isOver = false
    @g = $('#game')
    $(window).on('keypress', @keyCheck)
    @buildUI()


  keyCheck: (e) =>
    @roll() if e.charCode==114 || e.charCode == 82

  newGame: =>
    if (!@isOver && !confirm('Are you sure you want to start a new game?'))
      return
    super
    @rollCount = 0
    @isOver = false
    @ruleCount = 39
    @score = 0
    @bonus = 0
    @canScore = false
    @rolling = 0
    $('#game').html('');
    @buildUI()

  buildUI: ->
    super

    @rollbtn = $('<button id="rollbtn" class="btn btn-inverse btn-large">Roll</button>');
    @rollbtn.appendTo(@g);
    @rollbtn.on('click',@roll)

create dice

    h2 = $('<div class="dice clearfix"></div>');
    @d1 = new Die(1, h2);
    @d2 = new Die(2, h2);
    @d3 = new Die(3, h2);
    @d4 = new Die(4, h2);
    @d5 = new Die(5, h2);

    h2.appendTo(@g);

    @rulesv = $('<div class="rules"></div>');
    @rules2v = $('<div class="rules2"></div>')

    @rules = [];
    for i in [0..5] by 1
      @rules[i] = new NumRule(@).setNum(i+1)

    $('<div id="bonus-area">' +
      '<div class="bonus-line">Area Total: <span id="bonus-area-total">0</span></div>' +
      '<div class="bonus-line">Bonus At: <span>' + @bonus_at + '</span></div>' +
      '<div class="bonus-line">Bonus: <span id="bonus-given">0</span></div>')
      .appendTo(@rulesv);

    @rules[6] = new ofAKindRule(@).setNum(3)
    @rules[7] = new ofAKindRule(@).setNum(4)
    @rules[8] = new fullBoatRule(@)
    @rules[9] = new inARowRule(@).setLen(4).setVal(25)
    @rules[10] = new inARowRule(@).setLen(5).setVal(50)
    @rules[12] = new chanceRule(@)
    @rules[11] = new yatchRule(@)


    @rulesv.appendTo(@g)
    @rules2v.appendTo(@g)
    @bonusAreaTotal = $('#bonus-area-total')
    @bonusGiven = $('#bonus-given')

  append: (el) ->
    el.appendTo(@g);

  checkBonusScore: ->

    t = 0
    for i in [0..5] by 1
      t += @rules[i].getRuleScore()
    @bonusAreaTotal.text(t)
    if (@bonus > 0)
      return

    if (t >= @bonus_at)
      @bonus = 105
      @addToScore(@bonus)
      @bonusGiven.text(@bonus)

  addToScore: (n) ->
    @score += n
    @scoreView.text(@score)
    @checkBonusScore()
    @score

  getDieTotal: ->
    return @d1.num + @d2.num + @d3.num + @d4.num + @d5.num

  roll: =>
    return unless !@rolling
    @snd.roll.play()


    if (@rollCount == 0)
      @d1.reset()
      @d2.reset()
      @d3.reset()
      @d4.reset()
      @d5.reset()

    if (!@canScore)
      @canScore = true
      $('.cannotscore').removeClass('cannotscore')

    if (++@rollCount > 2)
      @rollbtn.attr('disabled','disabled');

    @d1.roll(@instantRoll)
    @d2.roll(@instantRoll)
    @d3.roll(@instantRoll)
    @d4.roll(@instantRoll)
    @d5.roll(@instantRoll)
    if (@instantRoll)
      @postRoll()
    else
      window.setTimeout(@postRoll, 10)

  postRoll: =>
    if ($.g.rolling)
      window.setTimeout($.g.postRoll, 10)
    else
      for r in $.g.rules
        r?.checkScore()

  nextTurn: ->
    @rollCount = 0
    @rollbtn.attr('disabled', false)
    @canScore = false

    if (--@ruleCount == 0)
      @isOver = true
      alert('Game Over!\nYou Scored:\n'+@score)
      @hi.addScore(@score)
      @rollbtn.attr('disabled','disabled');
    $('.scoreable').addClass('cannotscore')

Class for individual dice

class Die

  constructor: (id, appendTo) ->
    @num = @id = id
    @isOn = 0
    @anim_num = 0

    @el = $('<div class="die vert" id="die'+id+'">?</div>')
    @el.appendTo(appendTo)

    @el.on('click',@clicked)

  clicked: =>
    if (@isOn = !@isOn)
      @el.addClass('ison')
    else
      @el.removeClass('ison')

  roll: (instant) ->
    if (@isOn)
      return
    if (instant)
      for i in [1..6]
        @el.removeClass("die"+i)
      @num = Math.floor(Math.random()*6) + 1
      @el.addClass('die'+@num)
    else
      @animationCount = 0
      $.g.rolling++
      for i in [1..6]
        @el.removeClass("die"+i)
      window.setTimeout(@animateRoll, 100)

  animateRoll: =>
    if ++@animationCount > 10
      @num = @anim_num
      @animationInterval = window.clearInterval(@animationInterval)
      $.g.rolling--
    else
      @el.removeClass("die"+@anim_num)
      @anim_num = Math.floor(Math.random()*6) + 1
      @el.addClass('die'+@anim_num)
      window.setTimeout(@animateRoll, 100)

  reset: ->
    @num = 0
    @isOn = 0
    @el.text('?').removeClass('ison')

  resetAndRoll: ->
    @reset()
    @roll()

begin execution after page loads

$ ->

  $.g = new TrippleYatch('Tripple Yatch!');