# John Conway's Life # require 'rubycube' WIDTH = 100 HEIGHT = 100 NEIGHBORS = [[-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1]] RubyCube.start("Life", 800, 600) class Node attr_reader :r, :g, :b def initialize(x, y, posx, posy) @x, @y = x, y @r, @g, @b = 0, 0, 0 @alive = false @shape = Shape.circle(posx, posy, 3) @shape.hide() @shape.color(0, 0, 0) @state = false @next = false end def count_alive_neigbors() count = 0 NEIGHBORS.each { |delta| node = node_at(@x + delta[0], @y + delta[1]) if node and node.is_alive? then count += 1 end } return count end def alive() # build average color rtot, gtot, btot = 0, 0, 0 count = 0.0 NEIGHBORS.each { |delta| node = node_at(@x + delta[0], @y + delta[1]) if node and node.is_alive? then rtot += node.r gtot += node.g btot += node.b count += 1.0 end } # not enough color to sample, make one up if((rtot + gtot + btot) < 2.0) then @r = (rand(100)) / 100.0 @g = (rand(100)) / 100.0 @b = (rand(100)) / 100.0 else @r = (rtot / count) * 0.97 @g = (gtot / count) * 0.97 @b = (btot / count) * 0.97 end @shape.color(@r, @g, @b) @next = true end def die() @next = false end def tick() @state = @next if(@state) then @shape.show() else @shape.hide() end end def is_alive?() return @state end end # Create the board $map = [] 0.upto(HEIGHT) { |y| 0.upto(WIDTH) { |x| node = Node.new(x, y, x * 8, y * 6) $map[(y * WIDTH) + x] = node } } def node_at(x, y) return $map[(y * WIDTH) + x] end # Seed the middle of the board # stable block node_at(50, 50).alive() node_at(51, 50).alive() node_at(50, 49).alive() node_at(51, 49).alive() # blinker node_at(50, 46).alive() node_at(51, 46).alive() node_at(52, 46).alive() def grow() $map.each { |node| node.tick() } end grow() # --- Rules for life --- # # For a space that is 'populated': # Each cell with one or no neighbors dies, as if by loneliness. # Each cell with four or more neighbors dies, as if by overpopulation. # Each cell with two or three neighbors survives. # For a space that is 'empty' or 'unpopulated' # Each cell with three neighbors becomes populated. while(1) $map.each{ |node| count_alive_neigbors = node.count_alive_neigbors() if(node.is_alive?()) then if(count_alive_neigbors < 2) then node.die() elsif(count_alive_neigbors >= 4) then node.die() end elsif(count_alive_neigbors == 3) then node.alive() end } grow() end