conway_deathmatch 0.5.0.3 → 0.6.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 95413f3557aa8dcb568065213eb0e296c951aac2
4
- data.tar.gz: 7640ea076629eaab5134bed4f11288155916de58
2
+ SHA256:
3
+ metadata.gz: d20c966d1ffe3ac886d2315514779065ff4e17a3fd8c3927401eae066642bdba
4
+ data.tar.gz: de732dcf01de06570287852844cd87a6d629b448c27a73b111e4c4cc2cdcdad8
5
5
  SHA512:
6
- metadata.gz: 0ce56f027fdcf40ed302a65a928c22b9b7e3677c3c755505941a3546d1391bfb5af6810f9e092e19845d55d3d3cfd533954930e815d9f8d676305fc09b714e10
7
- data.tar.gz: abdedab43e2091b6a3f150e909685a90acaafe59022d73a6ce9003eb9d5b31a88fc2be44209238dd4a9339175c4043539ad85369a77106cc77bc489fa85ec33d
6
+ metadata.gz: 81dbf4124a1cc0a97410221405f52aad977a378f455f38eddc49896f387891731d32f37d45e0d9bf686cd8453faa6441363e20deb99affdb64c2ed8d4d372743
7
+ data.tar.gz: cce9be6dd2fb3a4dc2b047d39ec56dc14dbc81f2eb3301e4e8822ba11fefd5d3c291d187ede915fac6cf12d547fecfab4a565d88cbe3fc03cb7a7eadebd965e3
data/README.md CHANGED
@@ -1,8 +1,5 @@
1
- [![Build Status](https://travis-ci.org/rickhull/conway_deathmatch.svg?branch=master)](https://travis-ci.org/rickhull/conway_deathmatch)
1
+ [![CI Status](https://github.com/rickhull/conway_deathmatch/actions/workflows/ci.yaml/badge.svg)](https://github.com/rickhull/conway_deathmatch/actions/workflows/ci.yaml)
2
2
  [![Gem Version](https://badge.fury.io/rb/conway_deathmatch.svg)](http://badge.fury.io/rb/conway_deathmatch)
3
- [![Code Climate](https://codeclimate.com/github/rickhull/conway_deathmatch/badges/gpa.svg)](https://codeclimate.com/github/rickhull/conway_deathmatch)
4
- [![Dependency Status](https://gemnasium.com/rickhull/conway_deathmatch.svg)](https://gemnasium.com/rickhull/conway_deathmatch)
5
- [![Security Status](https://hakiri.io/github/rickhull/conway_deathmatch/master.svg)](https://hakiri.io/github/rickhull/conway_deathmatch/master)
6
3
 
7
4
  Introduction
8
5
  ===
data/Rakefile CHANGED
@@ -1,68 +1,117 @@
1
- require 'buildar'
2
-
3
- Buildar.new do |b|
4
- b.gemspec_file = 'conway_deathmatch.gemspec'
5
- b.version_file = 'VERSION'
6
- b.use_git = true
7
- end
8
-
9
- task default: %w[test bench]
10
- task travis: %w[test bench ruby-prof]
11
-
12
1
  require 'rake/testtask'
2
+
13
3
  desc "Run tests"
14
4
  Rake::TestTask.new do |t|
15
5
  t.name = "test"
16
- t.pattern = "test/test_*.rb"
17
- # t.warning = true
6
+ t.pattern = "test/*.rb"
7
+ t.warning = true
18
8
  end
19
9
 
20
10
  desc "Run benchmarks"
21
11
  Rake::TestTask.new do |t|
22
12
  t.name = "bench"
23
- t.pattern = "test/bench_*.rb"
24
- # t.warning = true
13
+ t.pattern = "test/bench/*.rb"
14
+ t.warning = true
25
15
  end
26
16
 
27
- desc "Generate code metrics reports"
28
- task :code_metrics => [:flog, :flay, :roodi] do
29
- end
17
+ task default: :test
30
18
 
31
- desc "Run flog on lib/"
32
- task :flog do
33
- puts
34
- sh "flog lib | tee metrics/flog"
19
+ #
20
+ # METRICS
21
+ #
22
+
23
+ metrics_tasks = []
24
+
25
+ begin
26
+ require 'flog_task'
27
+ FlogTask.new do |t|
28
+ t.threshold = 200
29
+ t.dirs = ['lib']
30
+ t.verbose = true
31
+ end
32
+ metrics_tasks << :flog
33
+ rescue LoadError
34
+ warn 'flog_task unavailable'
35
35
  end
36
36
 
37
- desc "Run flay on lib/"
38
- task :flay do
39
- puts
40
- sh "flay lib | tee metrics/flay"
37
+ begin
38
+ require 'flay_task'
39
+ FlayTask.new do |t|
40
+ t.dirs = ['lib']
41
+ t.verbose = true
42
+ end
43
+ metrics_tasks << :flay
44
+ rescue LoadError
45
+ warn 'flay_task unavailable'
41
46
  end
42
47
 
43
- desc "Run roodi on lib/"
44
- task :roodi do
45
- puts
46
- sh "roodi -config=.roodi.yml lib | tee metrics/roodi"
48
+ begin
49
+ require 'roodi_task'
50
+ RoodiTask.new config: '.roodi.yml', patterns: ['lib/**/*.rb']
51
+ metrics_tasks << :roodi
52
+ rescue LoadError
53
+ warn "roodi_task unavailable"
47
54
  end
48
55
 
56
+ desc "Generate code metrics reports"
57
+ task code_metrics: metrics_tasks
58
+
59
+
60
+ #
61
+ # PROFILING
62
+ #
63
+
49
64
  desc "Show current system load"
50
65
  task "loadavg" do
51
66
  puts File.read "/proc/loadavg"
52
67
  end
53
68
 
54
- # this runs against the installed gem lib, not git / filesystem
69
+ def lib_sh(cmd)
70
+ sh "RUBYLIB=lib #{cmd}"
71
+ end
72
+
73
+ def rprof_sh(script, args, rprof_args = '')
74
+ lib_sh ['ruby-prof', rprof_args, script, '--', args].join(' ')
75
+ end
76
+
77
+ rprof_args = "-m1"
78
+ xname = "bin/conway_deathmatch"
79
+ xargs = "-n 100 -s 0 --renderfinal"
80
+
55
81
  desc "Run ruby-prof on bin/conway_deathmatch (100 ticks)"
56
82
  task "ruby-prof" => "loadavg" do
57
- sh ["ruby-prof -m1 bin/conway_deathmatch",
58
- "-- -n100 -s0 --renderfinal",
59
- "| tee metrics/ruby-prof"].join(' ')
83
+ rprof_sh xname, xargs, rprof_args
60
84
  end
61
85
 
62
- # this runs against the installed gem lib, not git / filesystem
63
86
  desc "Run ruby-prof with --exclude-common-cycles"
64
87
  task "ruby-prof-exclude" => "ruby-prof" do
65
- sh ["ruby-prof -m1 --exclude-common-cycles bin/conway_deathmatch",
66
- "-- -n100 -s0 --renderfinal",
67
- "| tee metrics/ruby-prof-exclude"].join(' ')
88
+ rprof_sh xname, xargs, "#{rprof_args} --exclude-common-cycles"
68
89
  end
90
+
91
+ task "no-prof" do
92
+ lib_sh [xname, xargs].join(' ')
93
+ end
94
+
95
+ #
96
+ # GEM BUILD / PUBLISH
97
+ #
98
+
99
+ begin
100
+ require 'buildar'
101
+
102
+ Buildar.new do |b|
103
+ b.gemspec_file = 'conway_deathmatch.gemspec'
104
+ b.version_file = 'VERSION'
105
+ b.use_git = true
106
+ end
107
+ rescue LoadError
108
+ # ok
109
+ end
110
+
111
+
112
+ #
113
+ # TRAVIS CI
114
+ #
115
+
116
+ desc "Rake tasks for travis to run"
117
+ task travis: %w[test no-prof]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0.3
1
+ 0.6.2.1
@@ -1,31 +1,35 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- gem 'slop', '~> 3'
4
3
  require 'slop'
5
4
  require 'conway_deathmatch'
6
5
  require 'conway_deathmatch/shapes'
7
6
 
8
7
  # process cmdline options
9
8
  #
10
- opts = Slop.parse(help: true,
11
- banner: true,
12
- strict: true,
13
- optional_arguments: true) do
14
- banner 'Usage: conway_deathmatch [options]'
9
+ opts = Slop.parse do |o|
10
+ o.banner = "Usage: conway_deathmatch [options]"
11
+ o.int '-x', '--width', 'Grid width'
12
+ o.int '-y', '--height', 'Grid height'
13
+ o.int '-n', '--ticks', 'Max number of ticks to generate'
14
+ o.float '-s', '--sleep', 'Sleep duration'
15
+ o.string '-p', '--points', 'e.g. acorn 50 18 p 1 2 p 3 4'
16
+ o.bool '-g', '--step', 'Pause each tick for user input'
17
+ o.bool '-r', '--renderfinal', 'Only render the final state'
18
+ o.string '-d', '--deathmatch', 'single|aggressive|defensive|friendly'
19
+ o.string '--one', 'points for population "1"'
20
+ o.string '--two', 'points for population "2"'
21
+ o.string '--three', 'points for population "3"'
15
22
 
16
- on 'x', 'width=', '[int] Grid width', as: Integer
17
- on 'y', 'height=', '[int] Grid height', as: Integer
18
- # on 'D', 'dimensions=', '[str] width x height', as: String
19
- on 'n', 'ticks=', '[int] Max number of ticks to generate', as: Integer
20
- on 's', 'sleep=', '[flt] Sleep duration', as: Float
21
- on 'p', 'points=', '[str] e.g. "acorn 50 18 p 1 2 p 3 4"', as: String
22
- on 'g', 'step', 'Hold ticks for user input'
23
- on 'r', 'renderfinal', 'Only render the final state'
24
- on 'd', 'deathmatch',
25
- '[str] single|aggressive|defensive|friendly', as: String
26
- on 'one=', '[str] points for population "1"', as: String
27
- on 'two=', '[str] points for population "2"', as: String
28
- on 'three=', '[str] points for population "3"', as: String
23
+ o.on '-h', '--help' do
24
+ puts o
25
+ exit
26
+ end
27
+ end
28
+
29
+ def opts.error(msg = nil)
30
+ puts self
31
+ puts "ERROR: #{msg}" if msg
32
+ exit 1
29
33
  end
30
34
 
31
35
  width = opts[:width] || 70
@@ -40,7 +44,7 @@ deathmatch = case opts[:deathmatch].to_s.downcase
40
44
  when 'd', 'defensive' then :defensive
41
45
  when 'f', 'friendly' then :friendly
42
46
  else
43
- raise "unknown: #{opts[:deathmatch]}"
47
+ opts.error("unknown deathmatch option: #{opts[:deathmatch]}")
44
48
  end
45
49
 
46
50
  # create game
@@ -71,7 +75,7 @@ while n.nil? or count <= n
71
75
  b.tick
72
76
 
73
77
  if opts.step?
74
- gets
78
+ $stdin.gets
75
79
  else
76
80
  sleep slp if slp > 0.0
77
81
  end
@@ -1,37 +1,19 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'conway_deathmatch'
3
- s.version = File.read(File.join(__dir__, 'VERSION')).chomp
4
- s.summary = "Conway's Game of Life"
5
- s.description = "Deathmatch"
3
+ s.summary = "Conway's Game of Life, Deathmatch Edition (tm)"
4
+ s.description = "Several distinct populations competing for survival"
6
5
  s.authors = ["Rick Hull"]
7
6
  s.homepage = 'https://github.com/rickhull/conway_deathmatch'
8
7
  s.license = 'GPL'
9
- s.files = [
10
- 'conway_deathmatch.gemspec',
11
- 'VERSION',
12
- 'Rakefile',
13
- 'README.md',
14
- 'lib/conway_deathmatch.rb',
15
- 'lib/conway_deathmatch/shapes.rb',
16
- 'lib/conway_deathmatch/shapes/classic.yaml',
17
- 'lib/conway_deathmatch/shapes/discovered.yaml',
18
- 'bin/conway_deathmatch',
19
- 'bin/proving_ground',
20
- 'test/bench_grid.rb',
21
- 'test/spec_helper.rb',
22
- 'test/test_grid.rb',
23
- 'test/test_shapes.rb',
24
- ]
8
+
9
+ s.required_ruby_version = ">= 2"
10
+ s.version = File.read(File.join(__dir__, 'VERSION')).chomp
11
+
12
+ s.files = %w[conway_deathmatch.gemspec VERSION Rakefile README.md]
13
+ s.files += Dir['lib/**/*.rb']
14
+ s.files += Dir['test/**/*.rb']
15
+ s.files += Dir['bin/**/*.rb']
25
16
  s.executables = ['conway_deathmatch']
26
- s.add_runtime_dependency "slop", "~> 3.0"
27
- s.add_development_dependency "buildar", "~> 2"
28
- s.add_development_dependency "minitest", "~> 5"
29
- s.add_development_dependency "ruby-prof", "~> 0"
30
- s.add_development_dependency "flog", "~> 4.0"
31
- s.add_development_dependency "flay", "~> 2.0"
32
- s.add_development_dependency "roodi", "~> 4.0"
33
17
 
34
- # uncomment and set ENV['CODE_COVERAGE']
35
- # s.add_development_dependency "simplecov", "~> 0.9.0"
36
- s.required_ruby_version = "~> 2"
18
+ s.add_runtime_dependency "slop", "~> 4.0"
37
19
  end
@@ -1,15 +1,8 @@
1
- #require 'conway_deathmatch/shapes'
2
- #require 'lager'
3
-
4
1
  # Provides a 2d array for the grid
5
2
  # Implements standard and deathmatch evaluation rules
6
3
  # Boundaries are toroidal: they wrap in each direction
7
4
  #
8
5
  class ConwayDeathmatch
9
- #extend Lager
10
- #log_to $stderr
11
- class BoundsError < RuntimeError; end
12
-
13
6
  DEAD = '.'
14
7
  ALIVE = '0'
15
8
 
@@ -27,7 +20,6 @@ class ConwayDeathmatch
27
20
  @height = height
28
21
  @grid = self.class.new_grid(width, height)
29
22
  @deathmatch = deathmatch
30
- #@lager = self.class.lager
31
23
  end
32
24
 
33
25
  # Conway's Game of Life transition rules
@@ -3,8 +3,8 @@ require 'minitest/benchmark'
3
3
  require 'conway_deathmatch'
4
4
  require 'conway_deathmatch/shapes'
5
5
 
6
- BENCH_NEW_THRESH = (ENV['BENCH_NEW_THRESH'] || 0.9).to_f
7
- BENCH_TICK_THRESH = (ENV['BENCH_TICK_THRESH'] || 0.9995).to_f
6
+ bnew = (ENV['BENCH_NEW_THRESH'] || 0.9).to_f
7
+ btick = (ENV['BENCH_TICK_THRESH'] || 0.9995).to_f
8
8
  Shapes = ConwayDeathmatch::Shapes
9
9
 
10
10
  describe "ConwayDeathmatch.new Benchmark" do
@@ -12,7 +12,7 @@ describe "ConwayDeathmatch.new Benchmark" do
12
12
  bench_exp 9, 9999, 3
13
13
  end
14
14
 
15
- bench_performance_linear "width*height", BENCH_NEW_THRESH do |n|
15
+ bench_performance_linear "width*height", bnew do |n|
16
16
  ConwayDeathmatch.new(n, n)
17
17
  end
18
18
  end
@@ -22,14 +22,13 @@ describe "ConwayDeathmatch#tick Benchmark" do
22
22
  bench_exp 1, 100, 3
23
23
  end
24
24
 
25
- bench_performance_linear "acorn demo", BENCH_TICK_THRESH do |n|
25
+ bench_performance_linear "acorn demo", btick do |n|
26
26
  b = ConwayDeathmatch.new(70, 40)
27
27
  Shapes.add(b, "acorn 50 18")
28
28
  n.times { b.tick }
29
29
  end
30
30
 
31
- bench_performance_linear "aggressive deathmatch demo",
32
- BENCH_TICK_THRESH do |n|
31
+ bench_performance_linear "aggressive deathmatch demo", btick do |n|
33
32
  b = ConwayDeathmatch.new(70, 40)
34
33
  b.deathmatch = :aggressive
35
34
  Shapes.add(b, "acorn 30 30", "1")
@@ -37,8 +36,7 @@ describe "ConwayDeathmatch#tick Benchmark" do
37
36
  n.times { b.tick }
38
37
  end
39
38
 
40
- bench_performance_linear "defensive deathmatch demo",
41
- BENCH_TICK_THRESH do |n|
39
+ bench_performance_linear "defensive deathmatch demo", btick do |n|
42
40
  b = ConwayDeathmatch.new(70, 40)
43
41
  b.deathmatch = :defensive
44
42
  Shapes.add(b, "acorn 30 30", "1")
@@ -46,8 +44,7 @@ describe "ConwayDeathmatch#tick Benchmark" do
46
44
  n.times { b.tick }
47
45
  end
48
46
 
49
- bench_performance_linear "friendly deathmatch demo",
50
- BENCH_TICK_THRESH do |n|
47
+ bench_performance_linear "friendly deathmatch demo", btick do |n|
51
48
  b = ConwayDeathmatch.new(70, 40)
52
49
  b.deathmatch = :friendly
53
50
  Shapes.add(b, "acorn 30 30", "1")
data/test/grid.rb ADDED
@@ -0,0 +1,127 @@
1
+ require_relative 'helper'
2
+ require 'conway_deathmatch'
3
+
4
+ describe ConwayDeathmatch do
5
+ before do
6
+ @alive = ConwayDeathmatch::ALIVE
7
+ @dead = ConwayDeathmatch::DEAD
8
+ end
9
+
10
+ describe "an empty grid" do
11
+ before do
12
+ @x = 5
13
+ @y = 5
14
+ @grid = ConwayDeathmatch.new(@x, @y)
15
+ end
16
+
17
+ it "consists entirely of dead cells" do
18
+ expect(@grid.population[@dead]).must_equal @x * @y
19
+ expect(@grid.population.keys.length).must_equal 1
20
+ end
21
+
22
+ it "stays dead after a tick" do
23
+ expect(@grid.tick.population[@dead]).must_equal @x*@y
24
+ expect(@grid.population.keys.length).must_equal 1
25
+ end
26
+
27
+ it "can be populated by a 2x2 block" do
28
+ @grid.populate 1,1
29
+ @grid.populate 1,2
30
+ @grid.populate 2,1
31
+ @grid.populate 2,2
32
+
33
+ expect(@grid.population[@dead]).must_equal @x * @y - 4
34
+ expect(@grid.population[@alive]).must_equal 4
35
+
36
+ 0.upto(4) { |x|
37
+ 0.upto(4) { |y|
38
+ if x.between?(1, 2) and y.between?(1, 2)
39
+ expect(@grid.value(x, y)).must_equal @alive
40
+ else
41
+ expect(@grid.value(x, y)).must_equal @dead
42
+ end
43
+ }
44
+ }
45
+ end
46
+ end
47
+
48
+ describe "aggressive deathmatch" do
49
+ it "allows survivors to switch sides" do
50
+ # don't risk an infinite loop if a bug is present
51
+ 99.times {
52
+ @grid = ConwayDeathmatch.new(5, 3, :aggressive)
53
+ @grid.populate(1, 1, :team) # friendly
54
+ @grid.populate(2, 1, :team) # friendly; eventual survivor
55
+ @grid.populate(3, 1, :hostile) # enemy
56
+
57
+ @grid.tick
58
+
59
+ # exit the loop when the survivor switches sides
60
+ break if @grid.value(2, 1) == :hostile
61
+ }
62
+
63
+ # expect to fail once per 2^99 runs
64
+ expect(@grid.population.fetch(:team)).must_equal 2
65
+ expect(@grid.population.fetch(:hostile)).must_equal 1
66
+
67
+ # survivors
68
+ team = [[2, 0], [2, 2]]
69
+ hostile = [[2, 1]]
70
+
71
+ 0.upto(4) { |x|
72
+ 0.upto(2) { |y|
73
+ val = team.include?([x, y]) ? :team :
74
+ (hostile.include?([x, y]) ? :hostile : @dead)
75
+ expect(@grid.value(x, y)).must_equal(val)
76
+ }
77
+ }
78
+ end
79
+ end
80
+
81
+ describe "defensive deathmatch" do
82
+ it "won't allow survivors to switch sides" do
83
+ 16.times {
84
+ @grid = ConwayDeathmatch.new(5, 3, :defensive)
85
+ @grid.populate(1, 1, :team) # friendly
86
+ @grid.populate(2, 1, :team) # survivor
87
+ @grid.populate(3, 1, :hostile) # enemy
88
+ @grid.tick
89
+
90
+ expect(@grid.population.fetch(:team)).must_equal 3
91
+ 0.upto(4) { |x|
92
+ 0.upto(2) { |y|
93
+ if x == 2 and y.between?(0, 2)
94
+ expect(@grid.value(x, y)).must_equal :team
95
+ else
96
+ expect(@grid.value(x, y)).must_equal @dead
97
+ end
98
+ }
99
+ }
100
+ }
101
+ end
102
+ end
103
+
104
+ describe "friendly deathmatch" do
105
+ it "allows survivors even with excess hostiles nearby" do
106
+ @grid = ConwayDeathmatch.new(5, 5, :friendly)
107
+ @grid.populate(1, 2, :team) # friendly
108
+ @grid.populate(2, 2, :team) # friendly, eventual survivor
109
+ @grid.populate(3, 2, :team) # friendly
110
+ @grid.populate(2, 1, :hostile) # enemy
111
+ @grid.populate(2, 3, :hostile) # enemy
112
+ expect(@grid.population.fetch(:team)).must_equal 3
113
+ expect(@grid.population.fetch(:hostile)).must_equal 2
114
+
115
+ @grid.tick
116
+
117
+ # (2,2) alive despite 4 neighbors (2 friendly); now all else @dead
118
+ expect(@grid.population.fetch(:team)).must_equal 1
119
+ 0.upto(4) { |x|
120
+ 0.upto(4) { |y|
121
+ expect(@grid.value(x, y)).
122
+ must_equal(x == 2 && y == 2 ? :team : @dead)
123
+ }
124
+ }
125
+ end
126
+ end
127
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,50 @@
1
+ if ENV['CODE_COVERAGE'] and
2
+ !%w[false no].include?(ENV['CODE_COVERAGE'].downcase)
3
+
4
+ require 'simplecov'
5
+ require "simplecov_json_formatter"
6
+
7
+ class SimpleCov::Formatter::TextFormatter
8
+ FILENAME = 'metrics/coverage'
9
+
10
+ def format(result)
11
+ tot = result.files
12
+ rpt = ["Coverage: %0.1f%%" % tot.covered_percent,
13
+ "Strength: %0.2f" % tot.covered_strength,
14
+ " Lines: %i" % tot.lines_of_code,
15
+ " Covered: %i" % tot.covered_lines,
16
+ " N/A: %i" % tot.never_lines,
17
+ ]
18
+ if tot.missed_lines > 0
19
+ rpt << "Missed: %i" % tot.missed_lines
20
+ end
21
+ if tot.skipped_lines > 0
22
+ rpt << "Skipped: %i" % tot.skipped_lines
23
+ end
24
+ rpt << result.files.map { |sfile|
25
+ "%i%% (%i/%i)\t%s" % [sfile.covered_percent,
26
+ sfile.covered_lines.length,
27
+ sfile.lines_of_code,
28
+ sfile.filename]
29
+ }.join("\n")
30
+ rpt = rpt.join("\n")
31
+
32
+ puts
33
+ puts rpt
34
+ if File.writable?(FILENAME)
35
+ File.open(FILENAME, 'w') { |f|
36
+ f.write(rpt + "\n")
37
+ }
38
+ puts "wrote #{FILENAME}"
39
+ end
40
+ end
41
+ end
42
+
43
+ SimpleCov.formatters = [
44
+ SimpleCov::Formatter::TextFormatter,
45
+ SimpleCov::Formatter::JSONFormatter,
46
+ ]
47
+
48
+ SimpleCov.start
49
+ end
50
+ require 'minitest/autorun'
data/test/shapes.rb ADDED
@@ -0,0 +1,9 @@
1
+ require_relative 'helper'
2
+ require 'conway_deathmatch/shapes'
3
+
4
+ describe ConwayDeathmatch::Shapes do
5
+ it "recognizes acorn" do
6
+ expect(ConwayDeathmatch::Shapes.classic.fetch("acorn")).
7
+ must_be_instance_of Array
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'helper'
2
+ require 'conway_deathmatch'
3
+ require 'conway_deathmatch/shapes'
4
+
5
+ describe "Shapes on the grid" do
6
+ before do
7
+ @alive = ConwayDeathmatch::ALIVE
8
+ @grid = ConwayDeathmatch.new(20, 20)
9
+ ConwayDeathmatch::Shapes.add(@grid, "acorn 0 0")
10
+ end
11
+
12
+ it "recognizes \"acorn 0 0\"" do
13
+ ConwayDeathmatch::Shapes.classic.fetch("acorn").each { |xy_ary|
14
+ expect(@grid.value(*xy_ary)).must_equal @alive
15
+ }
16
+ expect(@grid.population.fetch(@alive)).must_equal 7
17
+ end
18
+
19
+ it "ticks correctly" do
20
+ @grid.tick
21
+ new_points = [
22
+ [0, 1],
23
+ [1, 1],
24
+ [2, 1],
25
+ [4, 1],
26
+ [4, 2],
27
+ [5, 1],
28
+ [5, 2],
29
+ [5, 3],
30
+ ].each { |xy_ary|
31
+ expect(@grid.value(*xy_ary)).must_equal @alive
32
+ }
33
+ expect(@grid.population.fetch(@alive)).must_equal new_points.length
34
+ end
35
+ end
metadata CHANGED
@@ -1,115 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conway_deathmatch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.3
4
+ version: 0.6.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Hull
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-27 00:00:00.000000000 Z
11
+ date: 1980-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '3.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '3.0'
27
- - !ruby/object:Gem::Dependency
28
- name: buildar
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2'
41
- - !ruby/object:Gem::Dependency
42
- name: minitest
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '5'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '5'
55
- - !ruby/object:Gem::Dependency
56
- name: ruby-prof
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: flog
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '4.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '4.0'
83
- - !ruby/object:Gem::Dependency
84
- name: flay
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '2.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '2.0'
97
- - !ruby/object:Gem::Dependency
98
- name: roodi
99
15
  requirement: !ruby/object:Gem::Requirement
100
16
  requirements:
101
17
  - - "~>"
102
18
  - !ruby/object:Gem::Version
103
19
  version: '4.0'
104
- type: :development
20
+ type: :runtime
105
21
  prerelease: false
106
22
  version_requirements: !ruby/object:Gem::Requirement
107
23
  requirements:
108
24
  - - "~>"
109
25
  - !ruby/object:Gem::Version
110
26
  version: '4.0'
111
- description: Deathmatch
112
- email:
27
+ description: Several distinct populations competing for survival
28
+ email:
113
29
  executables:
114
30
  - conway_deathmatch
115
31
  extensions: []
@@ -119,27 +35,25 @@ files:
119
35
  - Rakefile
120
36
  - VERSION
121
37
  - bin/conway_deathmatch
122
- - bin/proving_ground
123
38
  - conway_deathmatch.gemspec
124
39
  - lib/conway_deathmatch.rb
125
40
  - lib/conway_deathmatch/shapes.rb
126
- - lib/conway_deathmatch/shapes/classic.yaml
127
- - lib/conway_deathmatch/shapes/discovered.yaml
128
- - test/bench_grid.rb
129
- - test/spec_helper.rb
130
- - test/test_grid.rb
131
- - test/test_shapes.rb
41
+ - test/bench/grid.rb
42
+ - test/grid.rb
43
+ - test/helper.rb
44
+ - test/shapes.rb
45
+ - test/shapes_on_grid.rb
132
46
  homepage: https://github.com/rickhull/conway_deathmatch
133
47
  licenses:
134
48
  - GPL
135
49
  metadata: {}
136
- post_install_message:
50
+ post_install_message:
137
51
  rdoc_options: []
138
52
  require_paths:
139
53
  - lib
140
54
  required_ruby_version: !ruby/object:Gem::Requirement
141
55
  requirements:
142
- - - "~>"
56
+ - - ">="
143
57
  - !ruby/object:Gem::Version
144
58
  version: '2'
145
59
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -148,9 +62,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
62
  - !ruby/object:Gem::Version
149
63
  version: '0'
150
64
  requirements: []
151
- rubyforge_project:
152
- rubygems_version: 2.5.2
153
- signing_key:
65
+ rubygems_version: 3.4.4
66
+ signing_key:
154
67
  specification_version: 4
155
- summary: Conway's Game of Life
68
+ summary: Conway's Game of Life, Deathmatch Edition (tm)
156
69
  test_files: []
data/bin/proving_ground DELETED
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'set'
4
- gem 'slop', '~> 3'
5
- require 'slop'
6
- require 'conway_deathmatch'
7
- require 'conway_deathmatch/shapes'
8
-
9
- # process cmdline options
10
- #
11
- opts = Slop.parse(help: true,
12
- banner: true,
13
- strict: true,
14
- optional_arguments: true) do
15
- banner 'Usage: proving_ground [options]'
16
-
17
- on 'w', 'width=', '[int] Grid width', as: Integer
18
- on 'height=', '[int] Grid height', as: Integer
19
- on 'n', 'num_ticks=', '[int] Max number of ticks to generate', as: Integer
20
- on 'p', 'num_points=', '[int] Number of points to generate', as: Integer
21
- on 'm', 'max_collisions=', '[int] Max number of collisions', as: Integer
22
- end
23
-
24
- num_points = opts[:num_points] || 5
25
- width = opts[:width] || num_points * 5
26
- height = opts[:height] || num_points * 5
27
- num_ticks = opts[:num_ticks] || num_points * 5
28
- max_c = opts[:max_collisions] || num_points ** 2
29
-
30
- # choose center point
31
- # choose next point within 2 units randomly
32
- def generate_points(num_points, width, height)
33
- points = [[width / 2, height / 2]]
34
- count = 0
35
- while points.length < num_points
36
- raise("sanity check failed") if count > num_points * 2
37
- count += 1
38
- next_p = next_point(points.sample)
39
- if next_p[0].between?(0, width - 1) and next_p[1].between?(0, height - 1)
40
- points << next_p unless points.include?(next_p)
41
- else
42
- # debug
43
- puts "#{next_p.inspect} out of bounds"
44
- end
45
- end
46
- points
47
- end
48
-
49
- def next_point(prev_point)
50
- prev_point.map { |dim| random_within(dim, 2) }
51
- end
52
-
53
- def random_within(x, dist)
54
- new_x = x - dist + rand(dist * 2)
55
- new_x += 1 if new_x >= x
56
- new_x
57
- end
58
-
59
- def shape_str(points)
60
- points.map { |point| "p #{point[0]} #{point[1]}" }.join(' ')
61
- end
62
-
63
- def conclude!(results, w, h)
64
- results.each { |k, res|
65
- puts "#{k} population: #{res[0]}"
66
- puts "shape_str: #{shape_str(res[1])}"
67
- puts
68
- }
69
- puts "Grid: #{w}x#{h}"
70
-
71
- exit 0
72
- end
73
-
74
- results = { final: [0], peak: [0], score: [0], }
75
- seen = Set.new
76
- collisions = 0
77
-
78
- Signal.trap("INT") { conclude!(results, width, height) }
79
-
80
- loop {
81
- # generate a random shape
82
- points = generate_points(num_points, width, height)
83
-
84
- # have we seen these points before?
85
- hsh = points.hash
86
- if seen.member? hsh
87
- collisions += 1
88
- puts "X" * collisions
89
- break if collisions > max_c # exit the loop, stop generating points
90
- next
91
- end
92
- seen << hsh
93
-
94
- # initialize grid with generated shape
95
- b = ConwayDeathmatch.new(width, height)
96
- b.add_points(points)
97
-
98
- current = peak = score = 0 # track population (results)
99
- static_count = 0 # detect a stabilized grid
100
-
101
- # iterate the game of life
102
- num_ticks.times { |i|
103
- b.tick
104
-
105
- # evaluate grid
106
- last = current
107
- current = b.population[ConwayDeathmatch::ALIVE]
108
- peak = current if current > peak
109
- score += current * i
110
-
111
- # cease ticks for static or (soon-to-be) empty grids
112
- break if current < 3
113
- static_count = (current == last ? static_count + 1 : 0)
114
- break if static_count > 3
115
- }
116
-
117
- puts "#{current} (#{peak}) [#{score}]"
118
-
119
- # track the highest populators
120
- #
121
- if current > results[:final][0]
122
- results[:final] = [current, points]
123
- puts "\tLargest final: #{current}"
124
- end
125
-
126
- if peak > results[:peak][0]
127
- results[:peak] = [peak, points]
128
- puts "\tLargest peak: #{peak}"
129
- end
130
-
131
- if score > results[:score][0]
132
- results[:score] = [score, points]
133
- puts "\tLargest score: #{score}"
134
- end
135
- }
136
-
137
- conclude!(results, width, height)
@@ -1,175 +0,0 @@
1
- acorn:
2
- - [0, 2]
3
- - [1, 0]
4
- - [1, 2]
5
- - [3, 1]
6
- - [4, 2]
7
- - [5, 2]
8
- - [6, 2]
9
-
10
- beacon:
11
- - [0, 0]
12
- - [0, 1]
13
- - [1, 0]
14
- - [2, 3]
15
- - [3, 2]
16
- - [3, 3]
17
-
18
- beehive:
19
- - [0, 1]
20
- - [1, 0]
21
- - [1, 2]
22
- - [2, 0]
23
- - [2, 2]
24
- - [3, 1]
25
-
26
- blinker:
27
- - [0, 1]
28
- - [1, 1]
29
- - [2, 1]
30
-
31
- block:
32
- - [0, 0]
33
- - [0, 1]
34
- - [1, 0]
35
- - [1, 1]
36
-
37
- block_engine_count:
38
- - [0, 5]
39
- - [2, 4]
40
- - [2, 5]
41
- - [4, 1]
42
- - [4, 2]
43
- - [4, 3]
44
- - [6, 0]
45
- - [6, 1]
46
- - [6, 2]
47
- - [7, 1]
48
-
49
- block_engine_space:
50
- - [0, 0]
51
- - [0, 1]
52
- - [1, 0]
53
- - [1, 3]
54
- - [2, 0]
55
- - [2, 3]
56
- - [2, 4]
57
- - [3, 2]
58
- - [4, 0]
59
- - [4, 2]
60
- - [4, 3]
61
- - [4, 4]
62
-
63
- block_engine_stripe:
64
- - [0, 0]
65
- - [1, 0]
66
- - [2, 0]
67
- - [3, 0]
68
- - [4, 0]
69
- - [5, 0]
70
- - [6, 0]
71
- - [7, 0]
72
- - [9, 0]
73
- - [10, 0]
74
- - [11, 0]
75
- - [12, 0]
76
- - [13, 0]
77
- - [17, 0]
78
- - [18, 0]
79
- - [19, 0]
80
- - [26, 0]
81
- - [27, 0]
82
- - [28, 0]
83
- - [29, 0]
84
- - [30, 0]
85
- - [31, 0]
86
- - [32, 0]
87
- - [34, 0]
88
- - [35, 0]
89
- - [36, 0]
90
- - [37, 0]
91
- - [38, 0]
92
-
93
- boat:
94
- - [0, 0]
95
- - [0, 1]
96
- - [1, 0]
97
- - [1, 2]
98
- - [2, 1]
99
-
100
- diehard:
101
- - [0, 1]
102
- - [1, 1]
103
- - [1, 2]
104
- - [5, 2]
105
- - [6, 0]
106
- - [6, 2]
107
- - [7, 2]
108
-
109
- glider:
110
- - [0, 2]
111
- - [1, 0]
112
- - [1, 2]
113
- - [2, 1]
114
- - [2, 2]
115
-
116
- loaf:
117
- - [0, 1]
118
- - [1, 0]
119
- - [1, 2]
120
- - [2, 0]
121
- - [2, 3]
122
- - [3, 1]
123
- - [3, 2]
124
-
125
- lwss:
126
- - [0, 1]
127
- - [0, 3]
128
- - [1, 0]
129
- - [2, 0]
130
- - [3, 0]
131
- - [3, 3]
132
- - [4, 0]
133
- - [4, 1]
134
- - [4, 2]
135
-
136
- rpent:
137
- - [0, 1]
138
- - [1, 0]
139
- - [1, 1]
140
- - [1, 2]
141
- - [2, 0]
142
-
143
- swastika:
144
- - [0, 0]
145
- - [0, 1]
146
- - [0, 2]
147
- - [0, 3]
148
- - [0, 6]
149
- - [1, 3]
150
- - [1, 6]
151
- - [2, 3]
152
- - [2, 6]
153
- - [3, 0]
154
- - [3, 1]
155
- - [3, 2]
156
- - [3, 4]
157
- - [3, 5]
158
- - [3, 6]
159
- - [4, 0]
160
- - [4, 3]
161
- - [5, 0]
162
- - [5, 3]
163
- - [6, 0]
164
- - [6, 3]
165
- - [6, 4]
166
- - [6, 5]
167
- - [6, 6]
168
-
169
- toad:
170
- - [0, 1]
171
- - [0, 2]
172
- - [1, 3]
173
- - [2, 0]
174
- - [3, 1]
175
- - [3, 2]
@@ -1,112 +0,0 @@
1
- # discovered via proving_ground
2
- a4: # boner
3
- - [0, 2]
4
- - [1, 0]
5
- - [1, 1]
6
- - [2, 2]
7
-
8
- a5:
9
- - [0, 1]
10
- - [1, 3]
11
- - [2, 2]
12
- - [3, 0]
13
- - [3, 2]
14
-
15
- b5:
16
- - [0, 0]
17
- - [1, 0]
18
- - [1, 1]
19
- - [1, 2]
20
- - [2, 1]
21
-
22
- c5:
23
- - [0, 1]
24
- - [1, 0]
25
- - [1, 2]
26
- - [2, 2]
27
- - [3, 3]
28
-
29
- d5: # peace
30
- - [0, 2]
31
- - [1, 0]
32
- - [1, 1]
33
- - [2, 1]
34
- - [3, 0]
35
-
36
-
37
- e5: # cross (peace + 1)
38
- - [0, 1]
39
- - [1, 0]
40
- - [1, 1]
41
- - [1, 2]
42
- - [2, 1]
43
-
44
- a6: # zed
45
- - [0, 2]
46
- - [1, 0]
47
- - [1, 1]
48
- - [2, 3]
49
- - [2, 4]
50
- - [3, 2]
51
-
52
- b6: # trinary
53
- - [0, 2]
54
- - [1, 1]
55
- - [2, 2]
56
- - [2, 3]
57
- - [3, 2]
58
- - [4, 0]
59
-
60
- c6: # cardioid
61
- - [0, 0]
62
- - [0, 1]
63
- - [1, 1]
64
- - [1, 2]
65
- - [2, 0]
66
- - [2, 1]
67
-
68
- a7:
69
- - [0, 3]
70
- - [1, 4]
71
- - [1, 1]
72
- - [2, 0]
73
- - [2, 1]
74
- - [3, 2]
75
- - [4, 1]
76
-
77
- b7: # rocket
78
- - [0, 0]
79
- - [0, 1]
80
- - [0, 2]
81
- - [1, 3]
82
- - [2, 0]
83
- - [2, 1]
84
- - [2, 2]
85
-
86
- c7: # urawizardarry
87
- - [0, 0]
88
- - [1, 1]
89
- - [2, 2]
90
- - [3, 2]
91
- - [4, 3]
92
- - [5, 4]
93
- - [5, 5]
94
-
95
- d7: # A
96
- - [0, 2]
97
- - [1, 1]
98
- - [1, 3]
99
- - [2, 0]
100
- - [2, 1]
101
- - [2, 3]
102
- - [2, 4]
103
-
104
- a8: # A
105
- - [0, 2]
106
- - [1, 1]
107
- - [1, 2]
108
- - [2, 0]
109
- - [2, 1]
110
- - [3, 1]
111
- - [3, 2]
112
- - [4, 2]
data/test/spec_helper.rb DELETED
@@ -1,13 +0,0 @@
1
- if ENV['CODE_COVERAGE']
2
- require 'simplecov'
3
- SimpleCov.start
4
- end
5
-
6
- require 'minitest/spec'
7
- require 'minitest/autorun'
8
- require 'conway_deathmatch'
9
- require 'conway_deathmatch/shapes'
10
-
11
- ALIVE = ConwayDeathmatch::ALIVE
12
- DEAD = ConwayDeathmatch::DEAD
13
- Shapes = ConwayDeathmatch::Shapes
data/test/test_grid.rb DELETED
@@ -1,141 +0,0 @@
1
- require_relative './spec_helper'
2
-
3
- describe ConwayDeathmatch do
4
- describe "an empty grid" do
5
- before do
6
- @x = 5
7
- @y = 5
8
- @grid = ConwayDeathmatch.new(@x, @y)
9
- end
10
-
11
- it "must have dead population" do
12
- @grid.population[DEAD].must_equal @x * @y
13
- @grid.population.keys.length.must_equal 1
14
- end
15
-
16
- it "must still be dead after a tick" do
17
- @grid.tick.population[DEAD].must_equal @x*@y
18
- @grid.population.keys.length.must_equal 1
19
- end
20
-
21
- it "must accept a block" do
22
- @grid.populate 1,1
23
- @grid.populate 1,2
24
- @grid.populate 2,1
25
- @grid.populate 2,2
26
-
27
- @grid.population[DEAD].must_equal @x * @y - 4
28
- @grid.population[ALIVE].must_equal 4
29
-
30
- 0.upto(4) { |x|
31
- 0.upto(4) { |y|
32
- if x.between?(1, 2) and y.between?(1, 2)
33
- @grid.value(x, y).must_equal ALIVE
34
- else
35
- @grid.value(x, y).must_equal DEAD
36
- end
37
- }
38
- }
39
- end
40
- end
41
-
42
- describe "adding shapes" do
43
- before do
44
- @grid = ConwayDeathmatch.new(40, 40)
45
- Shapes.add(@grid, "acorn 0 0")
46
- end
47
-
48
- it "must recognize \"acorn 0 0\"" do
49
- Shapes.classic.fetch("acorn").each { |xy_ary|
50
- @grid.value(*xy_ary).must_equal ALIVE
51
- }
52
- @grid.population.fetch(ALIVE).must_equal 7
53
- end
54
-
55
- it "must tick correctly" do
56
- @grid.tick
57
- new_points = [
58
- [0, 1],
59
- [1, 1],
60
- [2, 1],
61
- [4, 1],
62
- [4, 2],
63
- [5, 1],
64
- [5, 2],
65
- [5, 3],
66
- ].each { |xy_ary|
67
- @grid.value(*xy_ary).must_equal ALIVE
68
- }
69
- @grid.population.fetch(ALIVE).must_equal new_points.length
70
- end
71
- end
72
-
73
- describe "aggressive deathmatch" do
74
- it "must allow survivors to switch sides" do
75
- 32.times {
76
- @grid = ConwayDeathmatch.new(5, 3, :aggressive)
77
- @grid.populate(1, 1, '1') # friendly
78
- @grid.populate(2, 1, '1') # survivor
79
- @grid.populate(3, 1, '2') # enemy
80
-
81
- @grid.tick
82
- break if @grid.value(2, 1) == '2'
83
- }
84
-
85
- @grid.population.fetch('1').must_equal 2
86
- @grid.population.fetch('2').must_equal 1
87
- 0.upto(4) { |x|
88
- 0.upto(2) { |y|
89
- if x == 2 and y.between?(0, 2)
90
- @grid.value(x, y).must_equal(y == 1 ? '2' : '1')
91
- else
92
- @grid.value(x, y).must_equal DEAD
93
- end
94
- }
95
- }
96
- end
97
- end
98
-
99
- describe "defensive deathmatch" do
100
- it "must not allow survivors to switch sides" do
101
- 16.times {
102
- @grid = ConwayDeathmatch.new(5, 3, :defensive)
103
- @grid.populate(1, 1, '1') # friendly
104
- @grid.populate(2, 1, '1') # survivor
105
- @grid.populate(3, 1, '2') # enemy
106
- @grid.tick
107
-
108
- @grid.population.fetch('1').must_equal 3
109
- 0.upto(4) { |x|
110
- 0.upto(2) { |y|
111
- if x == 2 and y.between?(0, 2)
112
- @grid.value(x, y).must_equal '1'
113
- else
114
- @grid.value(x, y).must_equal DEAD
115
- end
116
- }
117
- }
118
- }
119
- end
120
- end
121
-
122
- describe "friendly deathmatch" do
123
- it "must allow survivors with excess hostiles nearby" do
124
- @grid = ConwayDeathmatch.new(5, 5, :friendly)
125
- @grid.populate(1, 2, '1') # friendly
126
- @grid.populate(2, 2, '1') # survivor
127
- @grid.populate(3, 2, '1') # friendly
128
- @grid.populate(2, 1, '2') # enemy
129
- @grid.populate(2, 3, '2') # enemy
130
- @grid.tick
131
-
132
- @grid.population.fetch('1').must_equal 1
133
- # (2,2) alive despite 4 neighbors, only 2 friendly; all else DEAD
134
- 0.upto(4) { |x|
135
- 0.upto(4) { |y|
136
- @grid.value(x, y).must_equal (x == 2 && y == 2 ? '1' : DEAD)
137
- }
138
- }
139
- end
140
- end
141
- end
data/test/test_shapes.rb DELETED
@@ -1,15 +0,0 @@
1
- require_relative './spec_helper'
2
-
3
- describe Shapes do
4
- it "must recognize acorn" do
5
- Shapes.classic.fetch("acorn").must_be_instance_of Array
6
- end
7
-
8
- it "must confirm acorn on the grid" do
9
- @grid = ConwayDeathmatch.new(20, 20)
10
- Shapes.add(@grid, "acorn 0 0")
11
- Shapes.classic.fetch("acorn").each { |xy_ary|
12
- @grid.value(*xy_ary).must_equal ALIVE
13
- }
14
- end
15
- end