# Rule definition
survival = [2, 3]
birth = [3, 6]

# rule returns true if the cell should be alive
# on the next turn, and false if not.
rule = (alive, adjacent) ->
  if alive
    return adjacent in survival
  else
    return adjacent in birth

# Algorithm and setup, click arrow below to expand
do -> # fold

  # how many cells on our board
  rows = 20
  cols = 20

  board = ((0 for [0...cols]) for [0...rows])
  
  # make a grid from an HTML table with some CSS
  grid = table rows, cols,
    width: 300/cols, height: 300/cols
    font: Math.floor(260/cols) + 'px Arial'
    cursor: 'default'
  
  # this button applies the rule on the board
  adv = button 'advance', ->
    next = []
    for row in [0...rows]
      nextrow = []
      for col in [0...cols]
        n = neighbors(row, col)
        nextrow.push if rule(board[row][col], n) then 1 else 0
      next.push nextrow
    board = next
    draw()
  
  # draw fills grid based on board
  draw = ->
    for row in [0...rows]
      for col in [0...cols]
        # these lines show neighbor counts
        n = neighbors(row, col) or ''
        grid.cell(row, col).text(n)
        c = board[row][col]
        b = if c > 0 then 'orange' else 'white'
        grid.cell(row, col).css background: b
  
  # neighbors sums up cells adjacent to (row, col)
  neighbors = (row, col) ->
    wrap = (x, limit) -> (x + limit) % limit
    sum = 0
    for r in [row - 1 .. row + 1]
      for c in [col - 1 .. col + 1]
        if r isnt row or c isnt col
          sum += board[wrap(r, rows)][wrap(c, cols)]
    return sum
  
  # clicking on a cell toggles its value
  grid.cell().click (e) ->
    col = $(this).index()
    row = $(this).closest('tr').index()
    board[row][col] = 1 - board[row][col]
    draw()
  
  # The start/stop button toggles a timer that clicks advance.
  going = false
  toggle = button 'start', ->
    going = not going
    toggle.text if going then 'stop' else 'start'
    if going
      forever 1, ->
        adv.click()
        cells = $("td").length
        dead = $("td:empty").length
        if cells == dead
          toggle.click()
    else
      stop()

  # center the table and the button
  $('table,button').wrap('\x3Ccenter>')
  $('button').css('font-size', '90%').css('margin-top', '5px')
  draw()