conway 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -3
- data/bin/conway +2 -2
- data/lib/conway.rb +1 -0
- data/lib/conway/cell_location_lookup.rb +35 -0
- data/lib/conway/cell_space.rb +1 -1
- data/lib/conway/driver/ascii.rb +78 -0
- data/lib/conway/generation.rb +32 -7
- data/lib/conway/point.rb +1 -0
- data/lib/conway/potential_cell_collection.rb +25 -18
- data/spec/conway/cell_location_lookup_spec.rb +90 -0
- data/spec/conway/cell_space_spec.rb +2 -2
- data/spec/conway/generation_spec.rb +11 -0
- data/spec/conway/point_spec.rb +4 -0
- data/spec/conway/potential_cell_collection_spec.rb +39 -5
- metadata +9 -10
- data/lib/conway/visualizer/ascii.rb +0 -69
data/README.md
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
## Conway
|
2
2
|
A simple Game of Life implementation with foremost focus on object design.
|
3
3
|
|
4
|
-
It's currently
|
5
|
-
|
4
|
+
It's currently a bit leaky of object references and has not had efficiency
|
5
|
+
optimization.
|
6
6
|
|
7
7
|
Conway comes with a very simple ASCII visualizer. It can be invoked as
|
8
8
|
below, where the size argument determines the dimensions of the cell grid:
|
9
9
|
|
10
|
-
conway --size 25 --cells="2,3
|
10
|
+
conway --size 25 --cells="10,2 9,3 8,3 9,4 10,4"
|
11
11
|
conway -s 30 -c 2,3:3,3:3,2:2,2:3,4
|
12
12
|
|
13
13
|
Please feel free to send feedback via the
|
data/bin/conway
CHANGED
@@ -5,7 +5,7 @@ lib_dir = File.join(File.dirname(__FILE__), '..', 'lib')
|
|
5
5
|
$LOAD_PATH.unshift lib_dir if File.directory?(lib_dir)
|
6
6
|
|
7
7
|
require 'choice'
|
8
|
-
require 'conway/
|
8
|
+
require 'conway/driver/ascii'
|
9
9
|
|
10
10
|
PROGRAM_VERSION = 1
|
11
11
|
|
@@ -69,7 +69,7 @@ Signal.trap("INT") do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
live_points = ConwayCli.parse_points Choice[:cells]
|
72
|
-
grid = Conway::
|
72
|
+
grid = Conway::Driver::Ascii.new(Choice[:size], live_points)
|
73
73
|
|
74
74
|
grid.loop do |step|
|
75
75
|
puts step
|
data/lib/conway.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Conway
|
2
|
+
class CellLocationLookup
|
3
|
+
def initialize
|
4
|
+
@hash ||= {}
|
5
|
+
@point ||= Point.new(0,0)
|
6
|
+
end
|
7
|
+
|
8
|
+
def insert(cell_location)
|
9
|
+
@hash[cell_location.point] = cell_location
|
10
|
+
end
|
11
|
+
|
12
|
+
def retrieve(point_or_x, y=nil)
|
13
|
+
if y
|
14
|
+
point_or_x = @point.update(point_or_x, y)
|
15
|
+
end
|
16
|
+
@hash[point_or_x]
|
17
|
+
end
|
18
|
+
|
19
|
+
def locations
|
20
|
+
@hash.values
|
21
|
+
end
|
22
|
+
|
23
|
+
def count
|
24
|
+
locations.count
|
25
|
+
end
|
26
|
+
|
27
|
+
def empty?
|
28
|
+
!(count > 0)
|
29
|
+
end
|
30
|
+
|
31
|
+
def each(&block)
|
32
|
+
locations.each(&block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/conway/cell_space.rb
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "conway"
|
2
|
+
|
3
|
+
module Conway
|
4
|
+
module Driver
|
5
|
+
class Ascii
|
6
|
+
def initialize(size, starting_cells, loop_interval=0.25)
|
7
|
+
self.max_x = self.max_y = size
|
8
|
+
self.starting_cells = starting_cells
|
9
|
+
self.loop_interval = loop_interval
|
10
|
+
end
|
11
|
+
|
12
|
+
def loop
|
13
|
+
generation = Generation.new(starting_cells)
|
14
|
+
start = Time.now
|
15
|
+
|
16
|
+
puts "They live!!\n\n"
|
17
|
+
|
18
|
+
begin
|
19
|
+
lookup = generation.location_lookup
|
20
|
+
|
21
|
+
grid = generate_grid(lookup)
|
22
|
+
|
23
|
+
grid << current_stats(lookup)
|
24
|
+
grid << elapsed_time_since(start)
|
25
|
+
|
26
|
+
|
27
|
+
yield grid if block_given?
|
28
|
+
|
29
|
+
if lookup.empty?
|
30
|
+
puts "\nThey have all perished! D-:"
|
31
|
+
break
|
32
|
+
end
|
33
|
+
|
34
|
+
sleep(loop_interval)
|
35
|
+
end while(generation = generation.next)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
attr_accessor :max_x, :max_y, :starting_cells, :loop_interval
|
40
|
+
|
41
|
+
def generate_grid(lookup)
|
42
|
+
grid = ""
|
43
|
+
(1..max_y).each do |y|
|
44
|
+
(1..max_x).each do |x|
|
45
|
+
cell_char = cell_content_for(lookup, x, y)
|
46
|
+
grid << "|#{cell_char}"
|
47
|
+
end
|
48
|
+
grid << "|\n"
|
49
|
+
end
|
50
|
+
grid
|
51
|
+
end
|
52
|
+
|
53
|
+
def cell_content_for(lookup, x,y)
|
54
|
+
lookup.retrieve(x,y) ? "X" : " "
|
55
|
+
end
|
56
|
+
|
57
|
+
def current_stats(lookup)
|
58
|
+
stats = "Total objects: #{live_object_count} "
|
59
|
+
stats << "Total living cells: #{lookup.count}\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
def elapsed_time_since(start)
|
63
|
+
elapsed_minutes, elapsed_seconds = ((Time.now - start).to_i).divmod 60
|
64
|
+
"Elapsed time: #{elapsed_minutes} min, #{elapsed_seconds} secs\n"
|
65
|
+
end
|
66
|
+
|
67
|
+
def live_object_count
|
68
|
+
if ObjectSpace.respond_to?(:count_objects)
|
69
|
+
# Ruby 1.9.2
|
70
|
+
ObjectSpace.count_objects[:TOTAL]
|
71
|
+
else
|
72
|
+
# Ruby 1.8.7
|
73
|
+
ObjectSpace.live_objects
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/conway/generation.rb
CHANGED
@@ -1,16 +1,41 @@
|
|
1
1
|
module Conway
|
2
2
|
class Generation
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :location_lookup
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
|
7
|
-
|
5
|
+
def initialize(cell_locations, rule_set=RuleSet.new)
|
6
|
+
self.location_lookup = normalize_to_lookup cell_locations
|
7
|
+
self.rule_set = rule_set
|
8
8
|
end
|
9
9
|
|
10
10
|
def next
|
11
|
-
cell_space
|
12
|
-
|
13
|
-
Generation.new
|
11
|
+
cell_space = CellSpace.new(cell_coordinates)
|
12
|
+
cell_lookup = cell_space.apply(rule_set)
|
13
|
+
Generation.new cell_lookup, rule_set
|
14
|
+
end
|
15
|
+
|
16
|
+
def cell_coordinates
|
17
|
+
location_lookup.locations.map {|loc| loc.point }
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
attr_accessor :rule_set
|
22
|
+
attr_writer :location_lookup
|
23
|
+
|
24
|
+
def normalize_to_lookup(points)
|
25
|
+
return points unless points.kind_of?(Array)
|
26
|
+
|
27
|
+
lookup = CellLocationLookup.new
|
28
|
+
points.each do |point|
|
29
|
+
loc = point_to_location(point)
|
30
|
+
lookup.insert(loc)
|
31
|
+
end
|
32
|
+
|
33
|
+
lookup
|
34
|
+
end
|
35
|
+
|
36
|
+
def point_to_location(point)
|
37
|
+
@live_cell ||= LiveCell.new
|
38
|
+
CellLocation.new(@live_cell, point)
|
14
39
|
end
|
15
40
|
end
|
16
41
|
end
|
data/lib/conway/point.rb
CHANGED
@@ -1,45 +1,52 @@
|
|
1
1
|
module Conway
|
2
2
|
class PotentialCellCollection
|
3
|
+
attr_reader :live_cell_lookup
|
4
|
+
|
3
5
|
def initialize(live_locations)
|
6
|
+
self.live_cell_lookup = CellLocationLookup.new
|
7
|
+
self.potential_cell_lookup = CellLocationLookup.new
|
8
|
+
self.default_dead_cell = DeadCell.new
|
9
|
+
|
4
10
|
identify_potential_locations(live_locations)
|
5
11
|
end
|
6
12
|
|
7
13
|
def each_cell(&block)
|
8
|
-
|
9
|
-
|
10
|
-
neighbor_cells = neighbors.map {|n| n.cell }
|
14
|
+
potential_cell_lookup.each do |cell_location|
|
15
|
+
neighbor_cells = neighbor_cells_for(cell_location)
|
11
16
|
|
12
|
-
|
17
|
+
next_cell = block.call(cell_location.cell, neighbor_cells)
|
13
18
|
|
14
|
-
|
15
|
-
|
19
|
+
if next_cell.alive?
|
20
|
+
live_cell_lookup.insert(cell_location)
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
|
-
def live_cell_locations
|
20
|
-
potential_cell_locations.values.select{|loc| loc.cell.kind_of?(LiveCell) }
|
21
|
-
end
|
22
|
-
|
23
25
|
private
|
24
|
-
|
25
|
-
|
26
|
-
CellLocation.new(DeadCell.new, point)
|
27
|
-
end
|
28
|
-
end
|
26
|
+
attr_accessor :potential_cell_lookup, :default_dead_cell
|
27
|
+
attr_writer :live_cell_lookup
|
29
28
|
|
30
29
|
def identify_potential_locations(locations)
|
31
30
|
locations.each do |loc|
|
32
|
-
|
31
|
+
potential_cell_lookup.insert(loc)
|
33
32
|
neighbors_for(loc).each do |neighbor|
|
34
|
-
|
33
|
+
potential_cell_lookup.insert(neighbor)
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
38
|
+
def dead_cell_location(point)
|
39
|
+
CellLocation.new(default_dead_cell, point)
|
40
|
+
end
|
41
|
+
|
39
42
|
def neighbors_for(location)
|
40
43
|
location.adjacent_points.map do |point|
|
41
|
-
|
44
|
+
potential_cell_lookup.retrieve(point) || dead_cell_location(point)
|
42
45
|
end
|
43
46
|
end
|
47
|
+
|
48
|
+
def neighbor_cells_for(location)
|
49
|
+
neighbors_for(location).map {|n| n.cell }
|
50
|
+
end
|
44
51
|
end
|
45
52
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Conway
|
4
|
+
|
5
|
+
describe CellLocationLookup do
|
6
|
+
let(:point) { Point.new 1,1 }
|
7
|
+
let(:cell) { LiveCell.new }
|
8
|
+
let(:location) { CellLocation.new cell, point }
|
9
|
+
let(:lookup) { CellLocationLookup.new }
|
10
|
+
|
11
|
+
describe "#insert" do
|
12
|
+
it "accepts a CellLocation" do
|
13
|
+
lookup.insert location
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#retrieve" do
|
18
|
+
before { lookup.insert location }
|
19
|
+
|
20
|
+
it "looks up based on a point" do
|
21
|
+
lookup.retrieve(point).should eql(location)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "looks up based on x,y" do
|
25
|
+
lookup.retrieve(1,1).should eql(location)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#each" do
|
30
|
+
let(:point2) { Point.new 2,2 }
|
31
|
+
let(:location2) { CellLocation.new cell, point2 }
|
32
|
+
|
33
|
+
before do
|
34
|
+
lookup.insert location
|
35
|
+
lookup.insert location2
|
36
|
+
end
|
37
|
+
|
38
|
+
it "yields each location once" do
|
39
|
+
locations = []
|
40
|
+
lookup.each do |loc|
|
41
|
+
locations << loc
|
42
|
+
end
|
43
|
+
|
44
|
+
locations.should have(2).locations
|
45
|
+
locations.should include(location)
|
46
|
+
locations.should include(location2)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#locations" do
|
51
|
+
let(:point2) { Point.new 2,2 }
|
52
|
+
let(:location2) { CellLocation.new cell, point2 }
|
53
|
+
|
54
|
+
before do
|
55
|
+
lookup.insert location
|
56
|
+
lookup.insert location2
|
57
|
+
end
|
58
|
+
|
59
|
+
it "is all the contained locations" do
|
60
|
+
lookup.locations.should have(2).locations
|
61
|
+
lookup.locations.should include(location)
|
62
|
+
lookup.locations.should include(location2)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#count" do
|
67
|
+
let(:point2) { Point.new 2,2 }
|
68
|
+
let(:location2) { CellLocation.new cell, point2 }
|
69
|
+
|
70
|
+
before do
|
71
|
+
lookup.insert location
|
72
|
+
lookup.insert location2
|
73
|
+
end
|
74
|
+
|
75
|
+
it "is the number of contained locations" do
|
76
|
+
lookup.count.should == 2
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#empty?" do
|
81
|
+
context "when the count is 0" do
|
82
|
+
it { should be_empty }
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when the count is 1" do
|
86
|
+
before { subject.insert location }
|
87
|
+
it { should_not be_empty }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -11,8 +11,8 @@ describe CellSpace do
|
|
11
11
|
let(:space) { CellSpace.new [Point.new(0,0)] }
|
12
12
|
let(:rule_set) { RuleSet.new }
|
13
13
|
|
14
|
-
it "returns a
|
15
|
-
space.apply(rule_set).
|
14
|
+
it "returns a CellLocationLookup" do
|
15
|
+
space.apply(rule_set).should be_a_kind_of(CellLocationLookup)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -6,6 +6,17 @@ describe Generation do
|
|
6
6
|
let(:coordinates) { [Point.new(0,0), Point.new(1,1)] }
|
7
7
|
let(:generation) { Generation.new(coordinates) }
|
8
8
|
|
9
|
+
describe "#initialize" do
|
10
|
+
it "accepts an array of Points" do
|
11
|
+
expect { generation.next }.to_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it "accepts a CellLocationLookup" do
|
15
|
+
generation = Generation.new(CellLocationLookup.new)
|
16
|
+
expect { generation.next }.to_not raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
9
20
|
describe "#cell_coordinates" do
|
10
21
|
it "returns points of current live cells" do
|
11
22
|
generation.cell_coordinates.should have(2).points
|
data/spec/conway/point_spec.rb
CHANGED
@@ -5,7 +5,8 @@ include Conway
|
|
5
5
|
describe PotentialCellCollection do
|
6
6
|
let(:live_cell) { LiveCell.new }
|
7
7
|
let(:point) { Point.new(1,1) }
|
8
|
-
let(:
|
8
|
+
let(:cell_location) { CellLocation.new(live_cell, point) }
|
9
|
+
let(:initial_cells) { [cell_location] }
|
9
10
|
let(:collection) { PotentialCellCollection.new(initial_cells) }
|
10
11
|
|
11
12
|
describe "#each_cell" do
|
@@ -18,11 +19,38 @@ describe PotentialCellCollection do
|
|
18
19
|
yielded_cells.should include(live_cell)
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
context "when the cell is a LiveCell" do
|
23
|
+
it "does not retain the cell if it becomes a DeadCell" do
|
24
|
+
collection.each_cell do |cell, neighbors|
|
25
|
+
DeadCell.new
|
26
|
+
end
|
27
|
+
collection.live_cell_lookup.should be_empty
|
28
|
+
end
|
29
|
+
|
30
|
+
it "retains the cell if it remains a LiveCell" do
|
31
|
+
collection.each_cell do |cell, neighbors|
|
32
|
+
LiveCell.new
|
33
|
+
end
|
34
|
+
collection.live_cell_lookup.locations.should include(cell_location)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when the cell is a DeadCell" do
|
39
|
+
let(:cell_location) { CellLocation.new(DeadCell.new, point) }
|
40
|
+
|
41
|
+
it "does not retain the cell if it remains a DeadCell" do
|
42
|
+
collection.each_cell do |cell, neighbors|
|
43
|
+
DeadCell.new
|
44
|
+
end
|
45
|
+
collection.live_cell_lookup.should be_empty
|
46
|
+
end
|
47
|
+
|
48
|
+
it "retains the cell if it remains a LiveCell" do
|
49
|
+
collection.each_cell do |cell, neighbors|
|
50
|
+
LiveCell.new
|
51
|
+
end
|
52
|
+
collection.live_cell_lookup.locations.should include(cell_location)
|
24
53
|
end
|
25
|
-
collection.live_cell_locations.should be_empty
|
26
54
|
end
|
27
55
|
|
28
56
|
context "neighbors" do
|
@@ -53,7 +81,13 @@ describe PotentialCellCollection do
|
|
53
81
|
end
|
54
82
|
|
55
83
|
it "includes all neighboring DeadCells" do
|
84
|
+
yielded_neighbors = nil
|
85
|
+
collection.each_cell do |cell, neighbors|
|
86
|
+
yielded_neighbors = neighbors
|
87
|
+
break
|
88
|
+
end
|
56
89
|
|
90
|
+
(yielded_neighbors - [neighbor_cell]).any?{|c| c.alive?}.should be_false
|
57
91
|
end
|
58
92
|
end
|
59
93
|
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 25
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Matt Yoho
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-21 00:00:00 -05:00
|
19
18
|
default_executable: conway
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -26,7 +25,6 @@ dependencies:
|
|
26
25
|
requirements:
|
27
26
|
- - "="
|
28
27
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 19
|
30
28
|
segments:
|
31
29
|
- 0
|
32
30
|
- 1
|
@@ -47,15 +45,17 @@ files:
|
|
47
45
|
- MIT-LICENSE
|
48
46
|
- README.md
|
49
47
|
- lib/conway/cell_location.rb
|
48
|
+
- lib/conway/cell_location_lookup.rb
|
50
49
|
- lib/conway/cell_space.rb
|
51
50
|
- lib/conway/dead_cell.rb
|
51
|
+
- lib/conway/driver/ascii.rb
|
52
52
|
- lib/conway/generation.rb
|
53
53
|
- lib/conway/live_cell.rb
|
54
54
|
- lib/conway/point.rb
|
55
55
|
- lib/conway/potential_cell_collection.rb
|
56
56
|
- lib/conway/rule_set.rb
|
57
|
-
- lib/conway/visualizer/ascii.rb
|
58
57
|
- lib/conway.rb
|
58
|
+
- spec/conway/cell_location_lookup_spec.rb
|
59
59
|
- spec/conway/cell_location_spec.rb
|
60
60
|
- spec/conway/cell_space_spec.rb
|
61
61
|
- spec/conway/dead_cell_spec.rb
|
@@ -80,7 +80,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
80
|
requirements:
|
81
81
|
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
hash: 3
|
84
83
|
segments:
|
85
84
|
- 0
|
86
85
|
version: "0"
|
@@ -89,7 +88,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
88
|
requirements:
|
90
89
|
- - ">="
|
91
90
|
- !ruby/object:Gem::Version
|
92
|
-
hash: 3
|
93
91
|
segments:
|
94
92
|
- 0
|
95
93
|
version: "0"
|
@@ -99,8 +97,9 @@ rubyforge_project:
|
|
99
97
|
rubygems_version: 1.3.7
|
100
98
|
signing_key:
|
101
99
|
specification_version: 3
|
102
|
-
summary: A simple implementation of Conway's Game of Life with an ASCII visualizer . This version has significant reference leaks.
|
100
|
+
summary: A simple implementation of Conway's Game of Life with an ASCII visualizer . This version has fewer significant reference leaks.
|
103
101
|
test_files:
|
102
|
+
- spec/conway/cell_location_lookup_spec.rb
|
104
103
|
- spec/conway/cell_location_spec.rb
|
105
104
|
- spec/conway/cell_space_spec.rb
|
106
105
|
- spec/conway/dead_cell_spec.rb
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require "conway"
|
2
|
-
|
3
|
-
module Conway
|
4
|
-
module Visualizer
|
5
|
-
class Ascii
|
6
|
-
def initialize(size, starting_cells, loop_interval=0.25)
|
7
|
-
self.max_x = self.max_y = size
|
8
|
-
self.starting_cells = starting_cells
|
9
|
-
self.loop_interval = loop_interval
|
10
|
-
end
|
11
|
-
|
12
|
-
def loop
|
13
|
-
generation = Generation.new(starting_cells)
|
14
|
-
start = Time.now
|
15
|
-
|
16
|
-
puts "They live!!\n\n"
|
17
|
-
|
18
|
-
begin
|
19
|
-
live_cells = generation.cell_coordinates
|
20
|
-
|
21
|
-
if live_cells.count == 0
|
22
|
-
puts "\nThey have all perished! D-:"
|
23
|
-
break
|
24
|
-
end
|
25
|
-
|
26
|
-
grid = ""
|
27
|
-
(1..max_y).each do |y|
|
28
|
-
(1..max_x).each do |x|
|
29
|
-
cell_char = cell_content_for(live_cells, x,y)
|
30
|
-
grid << "|#{cell_char}"
|
31
|
-
end
|
32
|
-
grid << "|\n"
|
33
|
-
end
|
34
|
-
|
35
|
-
grid << "\n"
|
36
|
-
|
37
|
-
grid << "Total objects: #{live_object_count} "
|
38
|
-
grid << "Total living cells: #{live_cells.count}\n"
|
39
|
-
|
40
|
-
elapsed_minutes, elapsed_seconds = ((Time.now - start).to_i).divmod 60
|
41
|
-
grid << "Elapsed time: #{elapsed_minutes} min, #{elapsed_seconds} secs\n"
|
42
|
-
|
43
|
-
yield grid if block_given?
|
44
|
-
|
45
|
-
sleep(loop_interval)
|
46
|
-
end while(generation = generation.next)
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
attr_accessor :max_x, :max_y, :starting_cells, :loop_interval
|
51
|
-
|
52
|
-
def cell_content_for(points, x,y)
|
53
|
-
@comparison_point ||= Point.new(x,y)
|
54
|
-
@comparison_point.update(x,y)
|
55
|
-
points.detect {|p| p == @comparison_point } ? "X" : " "
|
56
|
-
end
|
57
|
-
|
58
|
-
def live_object_count
|
59
|
-
if ObjectSpace.respond_to?(:count_objects)
|
60
|
-
# Ruby 1.9.2
|
61
|
-
ObjectSpace.count_objects[:TOTAL]
|
62
|
-
else
|
63
|
-
# Ruby 1.8.7
|
64
|
-
ObjectSpace.live_objects
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|