Skip to content

Instantly share code, notes, and snippets.

@rondale-sc
Created February 21, 2012 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rondale-sc/1873277 to your computer and use it in GitHub Desktop.
Save rondale-sc/1873277 to your computer and use it in GitHub Desktop.
Conway's Game of Life
require 'pry'
require 'pp'
# --------------------------------------------------------------
# CONWAY'S GAME OF LIFE!
#
# Any live cell with fewer than two live neighbours dies, as if caused by under-population.
# Any live cell with two or three live neighbours lives on to the next generation.
# Any live cell with more than three live neighbours dies, as if by overcrowding.
# Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
# --------------------------------------------------------------
class Cell
attr_accessor :y, :x, :alive, :future_alive
def initialize(x,y,alive=false)
@x = x
@y = y
@alive = alive
end
def is_alive?(sum)
self.future_alive = if @alive
[2,3].include?(sum)
else
sum == 3
end
end
def set_next_generation
self.alive = self.future_alive
self.future_alive = nil
end
def to_s; @alive ? 'O' : "-" end
end
class Pattern
def initialize(origin_x, origin_y, pattern=nil)
@origin_x, @origin_y = origin_x, origin_y
@default_patterns = {
:acorn => [[-3,0],[-2,0],[-2,2],[0,1],[1,0],[2,0],[3,0]],
:glider => [[0,0],[0,1],[-1,2],[-1,0],[-2,0]],
:glider_gun => [[0,0],[-1,0],[-1,1],[-1,-1],[-2,2],[-2,-2],[-3,0],
[-4,3],[-5,3],[-4,-3],[-5,-3],[-6, 2],[-6,-2],
[-7,1],[-7,0],[-7,-1],[-16,0],[-17,0],[-16,1],
[-17,1],[3,3],[3,2],[3,1],[4,3],[4,2],[4,1],[5,4],
[5,0],[7,4],[7,5],[7,0],[7,-1],[17,2],[17,3],[18,2],
[18,3]]
}
@pattern = @default_patterns[pattern].nil? ? @default_patterns[:acorn] : @default_patterns[pattern]
end
def set_cells(cells)
@pattern.each do |(x,y)|
unless cells[@origin_x + x].nil? || cells[@origin_x + x][@origin_y + y].nil?
cells[@origin_y + y][@origin_x + x].alive = true;
end
end
end
end
class Game
def initialize(opts)
@pattern = opts.delete(:pattern)
@width = opts.delete(:width) || 100
@height = opts.delete(:height) || 100
@steps = opts.delete(:steps)
@cells = Array.new(@height) { |y| Array.new(@width) { |x| Cell.new(x,y) }}
@neighbors = [[-1, 0],[1, 0],[-1, 1],[0, 1],[1, 1],[-1, -1],[0, -1], [1, -1]]
end
def cells
@cells.reverse
end
def alive_cells
@cells.reverse.inject([]) {|m, row| row.each {|cell| m << cell if cell.alive }; m}
end
def debug_alive_cells
alive_cells.each do |cell|
puts "\n---------------------------------\n"
puts "Cell @ X:#{cell.x} Y:#{cell.y}\n"
puts "\t Alive Neighbor count: #{alive_neighbors(cell.x, cell.y)}"
puts "-----------------------------------\n"
end
alive_cells.map{|c| [c.x, c.y]}
end
def play
Pattern.new(@width / 2, @height / 2, @pattern ).set_cells(@cells)
(1..@steps).each_with_index do |i|
system('clear')
puts self.to_s
step
end
end
def step
@cells.reverse.each do |row|
row.each do |cell|
cell.is_alive? alive_neighbors(cell.x, cell.y)
end
end
@cells.each {|r| r.each {|c| c.set_next_generation }}
end
def alive_neighbors(x,y)
@neighbors.inject(0) do |sum, (neighbor_x, neighbor_y)|
if !@cells[y + neighbor_y].nil? && !@cells[y + neighbor_y][x + neighbor_x].nil? && @cells[y + neighbor_y][x + neighbor_x].alive
sum += 1
end
sum
end
end
def to_s
@cells.reverse.map { |row| row.join }.join("\n")
end
end
if __FILE__ == $0
puts Game.new(:width => 100, :height => 100, :steps => 1000, :pattern => :glider_gun).play
end
@rondale-sc
Copy link
Author

It's still a work in progress. Added support for patterns.

@rondale-sc
Copy link
Author

Wasn't properly checking all rules. Fixed that, and added the glider_gun pattern. Enjoy!

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