1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# @field size
ROWS = 27
COLUMNS = 110

# pre-populate the field with random cells with this density
DENSITY = 0.12

# speed of live (in frames per second)
FPS = 3

# generate a random field
@field = (0...ROWS).map{ |x| (0...COLUMNS).map{ |y| rand < DENSITY } }

# life is an endless loop
loop do
  # cheat
  system('clear')
  
  # draw the board
  (0...ROWS).each do |row|
    (0...COLUMNS).each do |col|
      print @field[row][col] ? '*' : ' '
    end
    puts
  end
  
  # wait for next frame
  sleep(1.0 / FPS.to_f)
  
  # create an offspring field
  offspring = @field.clone
  
  # method to determine if a neighbor cell is alive
  def alive?(row, col)
    return false if row < 0 || row >= ROWS
    return false if col < 0 || col >= COLUMNS
    @field[row][col]
  end
  
  # for each cell in the parent field
  (0...ROWS).each do |row|
    (0...COLUMNS).each do |col|
      # count living neighbors
      relatives = 0
      [-1, 0, 1].each do |row_off|
        [-1, 0, 1].each do |col_off|
          next if row_off == 0 && col_off == 0
          relatives += 1 if alive?(row + row_off, col + col_off)
        end
      end
      
      if @field[row][col]
        # if current cell is alive
        # and has 2 or 3 living neighbors, then stay alive, otherwise die
        offspring[row][col] = relatives == 2 || relatives == 3
      else
        # if the current cell is dead
        # and has exactly 3 living neighbors, then spring to live
        offspring[row][col] = relatives == 3
      end
    end
  end

  # the kids grow up
  @field = offspring
end