Skip to content

Instantly share code, notes, and snippets.

@mvlwn
Last active August 29, 2015 14:09
Show Gist options
  • Save mvlwn/1b08b2d142eb6b8d0ff5 to your computer and use it in GitHub Desktop.
Save mvlwn/1b08b2d142eb6b8d0ff5 to your computer and use it in GitHub Desktop.
Tijn's Game of Life
#!/usr/bin/env ruby
module Printer
def print(str)
puts str
end
end
class Game
include Printer
def initialize(size = 5, rounds = 2)
@size = size.to_i
@rounds = rounds.to_i
@world = World.new(@size)
@current_round = 1
end
def seed(alive_cell_coordinates = [[]])
@world.seed_life(alive_cell_coordinates)
end
def random_seeds
@world.seed_random_life
end
def start
print "Starting Tijn's Game of Life"
print "We live in a #{@size}x#{@size} world and we play #{@rounds} rounds"
@world.print_world
@rounds.times{ self.play_round }
end
def play_round
system('clear')
# print "--------------------------------------------"
# print "Tijn's Game of Life"
# print "Playing round #{@current_round}"
@world.annual_foresight
@world.next_year
@world.print_world
sleep 0.05
@current_round += 1
end
end
class World
include Printer
def initialize(size)
@size = size
@grid = create_grid
end
def seed_life(alive_cell_coordinates)
alive_cell_coordinates.each do |coordinates|
x = coordinates[0]
y = coordinates[1]
cell = @grid[x][y]
cell.give_life
print "Seeding cell #{cell.inspect} with life"
end
end
def seed_random_life
@grid.flatten.each{|cell| cell.give_life if [0,0,1].sample == 1 }
end
def annual_foresight
@grid.flatten.each{|cell| set_prospect_for(cell) }
end
def next_year
@grid.flatten.each{|cell| cell.call_prospect }
end
def print_world
print @grid.collect{|row| row.collect{|c| "#{c.alive? ? c.symbol : ' '}" }.join(' ') }.join("\n")
end
private
def create_grid
@size.times.collect do |x|
@size.times.collect do |y|
Cell.new(x, y)
end
end
end
def set_prospect_for(cell)
alive_neighbours = alive_neighbours_of(cell).size
dead_neighbours = dead_neighbours_of(cell).size
# Any live cell with fewer than two live neighbours dies, as if by needs caused by underpopulation.
# Any live cell with more than three live neighbours dies, as if by overcrowding.
if cell.alive? && (alive_neighbours < 2 || alive_neighbours > 3)
cell.prospect = :death
# Any live cell with two or three live neighbours lives, unchanged, to the next generation.
elsif cell.alive? && [2,3].include?(alive_neighbours)
# Any dead cell with exactly three live neighbours cells will come to life.
cell.prospect = :none
elsif cell.dead? && alive_neighbours == 3
cell.prospect = :birth
else
cell.prospect = :none
end
end
def alive_neighbours_of(cell)
neighbours_of(cell).select{|neighbour| neighbour.alive? }
end
def dead_neighbours_of(cell)
neighbours_of(cell).select{|neighbour| neighbour.dead? }
end
def neighbours_of(cell)
max = @size - 1
neighbours = []
neighbours << @grid[cell.x-1][cell.y-1] if cell.x > 0 && cell.y > 0
neighbours << @grid[cell.x] [cell.y-1] if cell.y > 0
neighbours << @grid[cell.x+1][cell.y-1] if cell.x < max && cell.y > 0
neighbours << @grid[cell.x-1][cell.y] if cell.x > 0
neighbours << @grid[cell.x+1][cell.y] if cell.x < max
neighbours << @grid[cell.x-1][cell.y+1] if cell.x > 0 && cell.y < max
neighbours << @grid[cell.x] [cell.y+1] if cell.y < max
neighbours << @grid[cell.x+1][cell.y+1] if cell.x < max && cell.y < max
neighbours
end
end
class Cell
attr_reader :x, :y, :age
attr_accessor :prospect
def initialize(x, y)
@x = x
@y = y
@alive = false
@prospect = :none
@age = 0
end
def give_life
@alive = true
end
def alive?
@alive
end
def dead?
!@alive
end
def symbol
if alive?
if age > 3
'o'
elsif age > 1
'-'
else
'.'
end
else
' '
end
end
def call_prospect
if alive? && @prospect == :death
@alive = false
@age = 0
elsif dead? && @prospect == :birth
@alive = true
@age = 0
elsif @prospect == :none
if alive?
@age += 1
end
else
raise "Your prospect #{@prospect} is impossible for your #{@alive} state"
end
end
end
size = ENV['SIZE'] || 100
rounds = ENV['ROUNDS'] || 400
game = Game.new(size, rounds)
# north_west_glider = [[2,1], [3,2], [1,3], [2,3], [3,3]]
# south_east_glider = [[14,15], [14,14], [13,13], [14,13], [15,13]]
# game.seed(north_west_glider)
# game.seed(north_west_glider.collect{|i| i.collect{|j| j+6 } })
# game.seed(south_east_glider)
# game.seed([[20,2], [21,2], [22,2]])
# game.seed([[2,20], [2,21], [2,22]])
game.random_seeds
game.start
@mvlwn
Copy link
Author

mvlwn commented Nov 9, 2014

Run game.rb from your terminal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment