conway_deathmatch 0.6.0.1 → 0.6.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +1 -4
- data/Rakefile +24 -19
- data/VERSION +1 -1
- data/conway_deathmatch.gemspec +11 -29
- data/lib/conway_deathmatch.rb +0 -8
- data/test/{bench_grid.rb → bench/grid.rb} +0 -0
- data/test/grid.rb +127 -0
- data/test/helper.rb +50 -0
- data/test/shapes.rb +9 -0
- data/test/shapes_on_grid.rb +35 -0
- metadata +15 -108
- data/bin/proving_ground +0 -136
- data/lib/conway_deathmatch/shapes/classic.yaml +0 -175
- data/lib/conway_deathmatch/shapes/discovered.yaml +0 -112
- data/test/spec_helper.rb +0 -12
- data/test/test_grid.rb +0 -141
- data/test/test_shapes.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d20c966d1ffe3ac886d2315514779065ff4e17a3fd8c3927401eae066642bdba
|
4
|
+
data.tar.gz: de732dcf01de06570287852844cd87a6d629b448c27a73b111e4c4cc2cdcdad8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81dbf4124a1cc0a97410221405f52aad977a378f455f38eddc49896f387891731d32f37d45e0d9bf686cd8453faa6441363e20deb99affdb64c2ed8d4d372743
|
7
|
+
data.tar.gz: cce9be6dd2fb3a4dc2b047d39ec56dc14dbc81f2eb3301e4e8822ba11fefd5d3c291d187ede915fac6cf12d547fecfab4a565d88cbe3fc03cb7a7eadebd965e3
|
data/README.md
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
[](https://github.com/rickhull/conway_deathmatch/actions/workflows/ci.yaml)
|
2
2
|
[](http://badge.fury.io/rb/conway_deathmatch)
|
3
|
-
[](https://codeclimate.com/github/rickhull/conway_deathmatch)
|
4
|
-
[](https://gemnasium.com/rickhull/conway_deathmatch)
|
5
|
-
[](https://hakiri.io/github/rickhull/conway_deathmatch/master)
|
6
3
|
|
7
4
|
Introduction
|
8
5
|
===
|
data/Rakefile
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
require 'rake/testtask'
|
2
|
+
|
2
3
|
desc "Run tests"
|
3
4
|
Rake::TestTask.new do |t|
|
4
5
|
t.name = "test"
|
5
|
-
t.pattern = "test
|
6
|
-
|
6
|
+
t.pattern = "test/*.rb"
|
7
|
+
t.warning = true
|
7
8
|
end
|
8
9
|
|
9
10
|
desc "Run benchmarks"
|
10
11
|
Rake::TestTask.new do |t|
|
11
12
|
t.name = "bench"
|
12
|
-
t.pattern = "test/
|
13
|
-
|
13
|
+
t.pattern = "test/bench/*.rb"
|
14
|
+
t.warning = true
|
14
15
|
end
|
15
16
|
|
16
|
-
task default:
|
17
|
-
|
17
|
+
task default: :test
|
18
18
|
|
19
19
|
#
|
20
20
|
# METRICS
|
@@ -37,8 +37,8 @@ end
|
|
37
37
|
begin
|
38
38
|
require 'flay_task'
|
39
39
|
FlayTask.new do |t|
|
40
|
-
t.verbose = true
|
41
40
|
t.dirs = ['lib']
|
41
|
+
t.verbose = true
|
42
42
|
end
|
43
43
|
metrics_tasks << :flay
|
44
44
|
rescue LoadError
|
@@ -58,7 +58,7 @@ task code_metrics: metrics_tasks
|
|
58
58
|
|
59
59
|
|
60
60
|
#
|
61
|
-
# PROFILING
|
61
|
+
# PROFILING
|
62
62
|
#
|
63
63
|
|
64
64
|
desc "Show current system load"
|
@@ -66,29 +66,34 @@ task "loadavg" do
|
|
66
66
|
puts File.read "/proc/loadavg"
|
67
67
|
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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"
|
73
80
|
|
74
81
|
desc "Run ruby-prof on bin/conway_deathmatch (100 ticks)"
|
75
82
|
task "ruby-prof" => "loadavg" do
|
76
|
-
|
83
|
+
rprof_sh xname, xargs, rprof_args
|
77
84
|
end
|
78
85
|
|
79
86
|
desc "Run ruby-prof with --exclude-common-cycles"
|
80
87
|
task "ruby-prof-exclude" => "ruby-prof" do
|
81
|
-
|
82
|
-
rubyprof, '--exclude-common-cycles', scriptname, '--',
|
83
|
-
scriptargs].join(' ')
|
88
|
+
rprof_sh xname, xargs, "#{rprof_args} --exclude-common-cycles"
|
84
89
|
end
|
85
90
|
|
86
91
|
task "no-prof" do
|
87
|
-
|
92
|
+
lib_sh [xname, xargs].join(' ')
|
88
93
|
end
|
89
94
|
|
90
95
|
#
|
91
|
-
# GEM BUILD / PUBLISH
|
96
|
+
# GEM BUILD / PUBLISH
|
92
97
|
#
|
93
98
|
|
94
99
|
begin
|
@@ -109,4 +114,4 @@ end
|
|
109
114
|
#
|
110
115
|
|
111
116
|
desc "Rake tasks for travis to run"
|
112
|
-
task travis: %w[test
|
117
|
+
task travis: %w[test no-prof]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.2.1
|
data/conway_deathmatch.gemspec
CHANGED
@@ -1,37 +1,19 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'conway_deathmatch'
|
3
|
-
s.
|
4
|
-
s.
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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", "~> 4.0"
|
27
|
-
s.add_development_dependency "buildar", "~> 3"
|
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", "< 6"
|
33
17
|
|
34
|
-
|
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
|
data/lib/conway_deathmatch.rb
CHANGED
@@ -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
|
File without changes
|
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,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,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conway_deathmatch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
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:
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slop
|
@@ -24,98 +24,8 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.0'
|
27
|
-
|
28
|
-
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '3'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '3'
|
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
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '4'
|
104
|
-
- - "<"
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: '6'
|
107
|
-
type: :development
|
108
|
-
prerelease: false
|
109
|
-
version_requirements: !ruby/object:Gem::Requirement
|
110
|
-
requirements:
|
111
|
-
- - ">="
|
112
|
-
- !ruby/object:Gem::Version
|
113
|
-
version: '4'
|
114
|
-
- - "<"
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: '6'
|
117
|
-
description: Deathmatch
|
118
|
-
email:
|
27
|
+
description: Several distinct populations competing for survival
|
28
|
+
email:
|
119
29
|
executables:
|
120
30
|
- conway_deathmatch
|
121
31
|
extensions: []
|
@@ -125,27 +35,25 @@ files:
|
|
125
35
|
- Rakefile
|
126
36
|
- VERSION
|
127
37
|
- bin/conway_deathmatch
|
128
|
-
- bin/proving_ground
|
129
38
|
- conway_deathmatch.gemspec
|
130
39
|
- lib/conway_deathmatch.rb
|
131
40
|
- lib/conway_deathmatch/shapes.rb
|
132
|
-
-
|
133
|
-
-
|
134
|
-
- test/
|
135
|
-
- test/
|
136
|
-
- test/
|
137
|
-
- 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
|
138
46
|
homepage: https://github.com/rickhull/conway_deathmatch
|
139
47
|
licenses:
|
140
48
|
- GPL
|
141
49
|
metadata: {}
|
142
|
-
post_install_message:
|
50
|
+
post_install_message:
|
143
51
|
rdoc_options: []
|
144
52
|
require_paths:
|
145
53
|
- lib
|
146
54
|
required_ruby_version: !ruby/object:Gem::Requirement
|
147
55
|
requirements:
|
148
|
-
- - "
|
56
|
+
- - ">="
|
149
57
|
- !ruby/object:Gem::Version
|
150
58
|
version: '2'
|
151
59
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -154,9 +62,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
62
|
- !ruby/object:Gem::Version
|
155
63
|
version: '0'
|
156
64
|
requirements: []
|
157
|
-
|
158
|
-
|
159
|
-
signing_key:
|
65
|
+
rubygems_version: 3.4.4
|
66
|
+
signing_key:
|
160
67
|
specification_version: 4
|
161
|
-
summary: Conway's Game of Life
|
68
|
+
summary: Conway's Game of Life, Deathmatch Edition (tm)
|
162
69
|
test_files: []
|
data/bin/proving_ground
DELETED
@@ -1,136 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'set'
|
4
|
-
require 'slop'
|
5
|
-
require 'conway_deathmatch'
|
6
|
-
require 'conway_deathmatch/shapes'
|
7
|
-
|
8
|
-
# process cmdline options
|
9
|
-
#
|
10
|
-
opts = Slop.parse do |o|
|
11
|
-
o.banner = "Usage: proving_ground [options]"
|
12
|
-
o.int '-w', '--width', 'Grid width'
|
13
|
-
o.int '--height', 'Grid height'
|
14
|
-
o.int '-n', '--num_ticks', 'Max number of ticks to generate'
|
15
|
-
o.int '-p', '--num_points', 'Number of points to generate'
|
16
|
-
o.int '-m', '--max_collisions', 'Max number of generation collisions'
|
17
|
-
o.on '-h', '--help' do
|
18
|
-
puts o
|
19
|
-
exit
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
num_points = opts[:num_points] || 5
|
24
|
-
width = opts[:width] || num_points * 5
|
25
|
-
height = opts[:height] || num_points * 5
|
26
|
-
num_ticks = opts[:num_ticks] || num_points * 5
|
27
|
-
max_c = opts[:max_collisions] || num_points ** 2
|
28
|
-
|
29
|
-
# choose center point
|
30
|
-
# choose next point within 2 units randomly
|
31
|
-
def generate_points(num_points, width, height)
|
32
|
-
points = [[width / 2, height / 2]]
|
33
|
-
count = 0
|
34
|
-
while points.length < num_points
|
35
|
-
raise("sanity check failed") if count > num_points * 2
|
36
|
-
count += 1
|
37
|
-
next_p = next_point(points.sample)
|
38
|
-
if next_p[0].between?(0, width - 1) and next_p[1].between?(0, height - 1)
|
39
|
-
points << next_p unless points.include?(next_p)
|
40
|
-
else
|
41
|
-
# debug
|
42
|
-
puts "#{next_p.inspect} out of bounds"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
points
|
46
|
-
end
|
47
|
-
|
48
|
-
def next_point(prev_point)
|
49
|
-
prev_point.map { |dim| random_within(dim, 2) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def random_within(x, dist)
|
53
|
-
new_x = x - dist + rand(dist * 2)
|
54
|
-
new_x += 1 if new_x >= x
|
55
|
-
new_x
|
56
|
-
end
|
57
|
-
|
58
|
-
def shape_str(points)
|
59
|
-
points.map { |point| "p #{point[0]} #{point[1]}" }.join(' ')
|
60
|
-
end
|
61
|
-
|
62
|
-
def conclude!(results, w, h)
|
63
|
-
results.each { |k, res|
|
64
|
-
puts "#{k} population: #{res[0]}"
|
65
|
-
puts "shape_str: #{shape_str(res[1])}"
|
66
|
-
puts
|
67
|
-
}
|
68
|
-
puts "Grid: #{w}x#{h}"
|
69
|
-
|
70
|
-
exit 0
|
71
|
-
end
|
72
|
-
|
73
|
-
results = { final: [0, []], peak: [0, []], score: [0, []], }
|
74
|
-
seen = Set.new
|
75
|
-
collisions = 0
|
76
|
-
|
77
|
-
Signal.trap("INT") { conclude!(results, width, height) }
|
78
|
-
|
79
|
-
loop {
|
80
|
-
# generate a random shape
|
81
|
-
points = generate_points(num_points, width, height)
|
82
|
-
|
83
|
-
# have we seen these points before?
|
84
|
-
hsh = points.hash
|
85
|
-
if seen.member? hsh
|
86
|
-
collisions += 1
|
87
|
-
puts "X" * collisions
|
88
|
-
break if collisions > max_c # exit the loop, stop generating points
|
89
|
-
next
|
90
|
-
end
|
91
|
-
seen << hsh
|
92
|
-
|
93
|
-
# initialize grid with generated shape
|
94
|
-
b = ConwayDeathmatch.new(width, height)
|
95
|
-
b.add_points(points)
|
96
|
-
|
97
|
-
current = peak = score = 0 # track population (results)
|
98
|
-
static_count = 0 # detect a stabilized grid
|
99
|
-
|
100
|
-
# iterate the game of life
|
101
|
-
num_ticks.times { |i|
|
102
|
-
b.tick
|
103
|
-
|
104
|
-
# evaluate grid
|
105
|
-
last = current
|
106
|
-
current = b.population[ConwayDeathmatch::ALIVE]
|
107
|
-
peak = current if current > peak
|
108
|
-
score += current * i
|
109
|
-
|
110
|
-
# cease ticks for static or (soon-to-be) empty grids
|
111
|
-
break if current < 3
|
112
|
-
static_count = (current == last ? static_count + 1 : 0)
|
113
|
-
break if static_count > 3
|
114
|
-
}
|
115
|
-
|
116
|
-
puts "#{current} (#{peak}) [#{score}]"
|
117
|
-
|
118
|
-
# track the highest populators
|
119
|
-
#
|
120
|
-
if current > results[:final][0]
|
121
|
-
results[:final] = [current, points]
|
122
|
-
puts "\tLargest final: #{current}"
|
123
|
-
end
|
124
|
-
|
125
|
-
if peak > results[:peak][0]
|
126
|
-
results[:peak] = [peak, points]
|
127
|
-
puts "\tLargest peak: #{peak}"
|
128
|
-
end
|
129
|
-
|
130
|
-
if score > results[:score][0]
|
131
|
-
results[:score] = [score, points]
|
132
|
-
puts "\tLargest score: #{score}"
|
133
|
-
end
|
134
|
-
}
|
135
|
-
|
136
|
-
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,12 +0,0 @@
|
|
1
|
-
if ENV['CODE_COVERAGE']
|
2
|
-
require 'simplecov'
|
3
|
-
SimpleCov.start
|
4
|
-
end
|
5
|
-
|
6
|
-
require 'minitest/autorun'
|
7
|
-
require 'conway_deathmatch'
|
8
|
-
require 'conway_deathmatch/shapes'
|
9
|
-
|
10
|
-
ALIVE = ConwayDeathmatch::ALIVE
|
11
|
-
DEAD = ConwayDeathmatch::DEAD
|
12
|
-
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
|