Skip to content

Instantly share code, notes, and snippets.

@thatrubylove
Last active August 29, 2015 14:01
Show Gist options
  • Save thatrubylove/d299bee42f17376d9023 to your computer and use it in GitHub Desktop.
Save thatrubylove/d299bee42f17376d9023 to your computer and use it in GitHub Desktop.
Functional Game of Life (spike)
require 'curses'
module Seeder
extend self
def generate_matrix
rand(40..200).times.map { [rand(24), rand(48)] }
end
end
class Universe
attr_reader :cells
def initialize(cells=[], size=[10,10])
@cells = cells
@rows, @columns = *size
end
def living_cell?(x,y)
@cells.include?([x,y])
end
def dead_cell?(x,y)
!living_cell?(x,y)
end
def neighborhood(position, cell_position)
pos_x, pos_y = *position
cpos_x, cpos_y = *cell_position
[(pos_x - cpos_x).abs, (pos_y - cpos_y).abs]
end
def neighbors_to(x,y)
@cells.select do |cell_x, cell_y|
position = [x,y]
cell_position = [cell_x, cell_y]
lives_near?(neighborhood(position, cell_position))
end
end
def lives_near?(position)
x, y = *position
x <= 1 && y <= 1 && !(x == 0 && y == 0)
end
def seed_generation
rows, columns = [(0...@rows).to_a, (0...@columns).to_a]
rows.product(columns).select {|x, y| is_viable?(x,y) }
end
def neighbor_count_near(x,y)
neighbors_to(x,y).count
end
def has_2_or_3_neighbors?(x,y)
has_2_neighbors?(x,y) || has_3_neighbors?(x,y)
end
def has_2_neighbors?(x,y)
neighbor_count_near(x,y) == 2
end
def has_3_neighbors?(x,y)
neighbor_count_near(x,y) == 3
end
def should_survive?(x,y)
living_cell?(x,y) && has_2_or_3_neighbors?(x,y)
end
def should_ressurect?(x,y)
dead_cell?(x,y) && has_3_neighbors?(x,y)
end
def is_viable?(x,y)
should_survive?(x,y) || should_ressurect?(x,y)
end
def draw
Curses.setpos(0, 0)
Curses.addstr(0.upto(@rows - 1).map {|x| cells_on(x) }.join("\n"))
Curses.refresh
end
def cells_on(x)
0.upto(@columns - 1).map {|y| draw_cell(x, y) }.join
end
def draw_cell(x, y)
living_cell?(x, y) ? "∆" : " "
end
end
module Game
extend self
BOUNDS = [24, 48]
def run(seed)
iterations = 0
while true
last_seed = seed
universe = universe_from(seed)
universe.draw
seed = universe.seed_generation
iterations += 1
reseed if should_break?(last_seed, seed)
sleep 0.05
end
end
private
def reseed
Game.run(Seeder.generate_matrix)
end
def should_break?(last, this)
last == this || this.empty?
end
def universe_from(seed)
Universe.new(seed, BOUNDS)
end
end
Game.run(Seeder.generate_matrix)
@thatrubylove
Copy link
Author

Some comments and retweets and favs and I will clean this up using TDD with y'all. Show me you give a shit.... or not, and I will start hacking on other things.

Personally, I find the #gameoflife very interesting and we could doo all kinds of shit to it - collect stats, record unique shapes, machine learning.... the list goes on and on.... #becausefunctional

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