conway_deathmatch 0.3.2.3 → 0.3.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +114 -0
- data/Rakefile +23 -0
- data/VERSION +1 -0
- data/conway_deathmatch.gemspec +28 -0
- data/lib/conway_deathmatch/board_state.rb +3 -4
- data/test/bench_board_state.rb +31 -0
- data/test/spec_helper.rb +22 -0
- data/test/test_board_state.rb +53 -0
- data/test/test_shapes.rb +15 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c2b0b7a5f1a97dd224542429ceb5d288e61ed2f
|
4
|
+
data.tar.gz: 77d40e41599218e8e315a4661e77e37130a7187a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5686348c544509c2843456d23e3f296a77e38dd66705851b916a2998cc86e01bcf3310c7f3e86a4642e8a7bb47b8e20ecf2419b296068f6f125ad270e4195be1
|
7
|
+
data.tar.gz: d56b0a39e7a10760eef7abb8a13e6da5a24af3f3080def4e58d9c9bbafc3990a7be5e257d0d4487d967aabd7d53f82af682a918e0e24a1784c4594e69557fbe4
|
data/README.md
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/rickhull/conway_deathmatch.svg?branch=master)](https://travis-ci.org/rickhull/conway_deathmatch)
|
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
|
+
|
7
|
+
Introduction
|
8
|
+
===
|
9
|
+
|
10
|
+
[Conway's Game of Life](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)
|
11
|
+
is a small, simple set of rules for
|
12
|
+
[cellular automata](http://en.wikipedia.org/wiki/Cellular_automaton).
|
13
|
+
Operating like a simulation, there is a starting state where certain points on
|
14
|
+
a 2 dimensional board are populated, and the rules of the game determine the
|
15
|
+
next state, generating interesting, unpredictable, and ultimately lifelike
|
16
|
+
patterns over time.
|
17
|
+
|
18
|
+
This project was inspired by http://gameoflifetotalwar.com/ (hereafter CGOLTW).
|
19
|
+
You should check it out. It updates the classic set of rules, which support
|
20
|
+
only a single population, for multiple populations which are able to compete
|
21
|
+
for space and population.
|
22
|
+
|
23
|
+
This project exists not to compete with CGOLTW but as a supplementary
|
24
|
+
project for exploration and learning. My initial motivation was to make a
|
25
|
+
"proving ground" for searching for simple shapes and patterns with high birth
|
26
|
+
rates for determining successful CGOLTW strategies.
|
27
|
+
|
28
|
+
Usage
|
29
|
+
===
|
30
|
+
|
31
|
+
Requirements
|
32
|
+
---
|
33
|
+
|
34
|
+
* Ruby 2.0 or newer (`__dir__` is used in the gemspec and for shape loading)
|
35
|
+
|
36
|
+
|
37
|
+
Install
|
38
|
+
---
|
39
|
+
|
40
|
+
gem install conway_deathmatch
|
41
|
+
|
42
|
+
Demo
|
43
|
+
---
|
44
|
+
|
45
|
+
# defaults to 70x40 board and an acorn shape
|
46
|
+
conway_deathmatch
|
47
|
+
|
48
|
+
# multiplayer
|
49
|
+
conway_deathmatch --one "acorn 30 30" --two "die_hard 20 10"
|
50
|
+
|
51
|
+
Available Shapes
|
52
|
+
---
|
53
|
+
|
54
|
+
[Definitions](https://github.com/rickhull/conway_deathmatch/blob/master/lib/conway_deathmatch/data/shapes.yaml)
|
55
|
+
|
56
|
+
* acorn
|
57
|
+
* beacon
|
58
|
+
* beehive
|
59
|
+
* blinker
|
60
|
+
* block
|
61
|
+
* block_engine_count (block engine, minimal point count)
|
62
|
+
* block_engine_space (block engine, minimal footprint)
|
63
|
+
* block_engine_stripe (block engine, 1 point tall)
|
64
|
+
* boat
|
65
|
+
* die_hard
|
66
|
+
* glider
|
67
|
+
* loaf
|
68
|
+
* lwss (lightweight spaceship)
|
69
|
+
* rpent (R-pentomino)
|
70
|
+
* swastika
|
71
|
+
* toad
|
72
|
+
|
73
|
+
Implementation
|
74
|
+
===
|
75
|
+
|
76
|
+
Just one file, aside from shape loading: [Have a look-see](https://github.com/rickhull/conway_deathmatch/blob/master/lib/conway_deathmatch/board_state.rb)
|
77
|
+
|
78
|
+
This implementation emphasizes simplicity and ease of understanding. Currently
|
79
|
+
there are no performance optimizations. I would like to use this project
|
80
|
+
to demonstrate the process of optimization, ideally adding optimization on
|
81
|
+
an optional, parallel, or otherwise non-permanent basis -- i.e. maintain the
|
82
|
+
simple, naive implementation for reference and correctness.
|
83
|
+
|
84
|
+
Inspiration
|
85
|
+
---
|
86
|
+
Coming into this project, I had significant background knowledge concerning
|
87
|
+
Conway's Game of Life, but I could not have recited the basic rules in any
|
88
|
+
form. After being inspired by competing in CGOLTW, I read their [one background
|
89
|
+
page](http://gameoflifetotalwar.com/how-to-play) and then the
|
90
|
+
[wikipedia page](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). I
|
91
|
+
deliberately avoided any knowledge of any other implementations,
|
92
|
+
considering this project's implementation as of November 24 (2014) to be the
|
93
|
+
naive, simple approach.
|
94
|
+
|
95
|
+
Researched optimizations are now an immediate priority.
|
96
|
+
|
97
|
+
Caveats
|
98
|
+
---
|
99
|
+
|
100
|
+
### Boundaries
|
101
|
+
|
102
|
+
As currently implemented, this project uses fixed boundaries, and boundary
|
103
|
+
behavior is not standardized to my knowledge. For this project, points out of
|
104
|
+
bounds are treated as always-dead and unable-to-be-populated.
|
105
|
+
|
106
|
+
### Multiplayer
|
107
|
+
|
108
|
+
The rules for multiplayer are not standardized. I read about the CGOLTW
|
109
|
+
approach, and this project's approach is similar but different. In CGOLTW,
|
110
|
+
there are always 3 populations, and one population (civilians) is special, in
|
111
|
+
that civilians are born where there is birthright contention. Birthright
|
112
|
+
contention happens when a new cell must be generated, but none of the
|
113
|
+
neighboring parents have a unique plurality. For this project, birthright
|
114
|
+
contention is resolved with a random selection (TODO).
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'buildar'
|
2
|
+
|
3
|
+
Buildar.new do |b|
|
4
|
+
b.gemspec_file = 'conway_deathmatch.gemspec'
|
5
|
+
b.version_file = 'VERSION'
|
6
|
+
end
|
7
|
+
|
8
|
+
task default: %w[test bench]
|
9
|
+
|
10
|
+
require 'rake/testtask'
|
11
|
+
desc "Run tests"
|
12
|
+
Rake::TestTask.new do |t|
|
13
|
+
t.name = "test"
|
14
|
+
t.pattern = "test/test_*.rb"
|
15
|
+
# t.warning = true
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Run benchmarks"
|
19
|
+
Rake::TestTask.new do |t|
|
20
|
+
t.name = "bench"
|
21
|
+
t.pattern = "test/bench_*.rb"
|
22
|
+
# t.warning = true
|
23
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.2.5
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
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"
|
6
|
+
s.authors = ["Rick Hull"]
|
7
|
+
s.homepage = 'https://github.com/rickhull/conway_deathmatch'
|
8
|
+
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/board_state.rb',
|
16
|
+
'lib/conway_deathmatch/shapes.rb',
|
17
|
+
'lib/conway_deathmatch/data/shapes.yaml',
|
18
|
+
'bin/conway_deathmatch',
|
19
|
+
'test/bench_board_state.rb',
|
20
|
+
'test/spec_helper.rb',
|
21
|
+
'test/test_board_state.rb',
|
22
|
+
'test/test_shapes.rb',
|
23
|
+
]
|
24
|
+
s.executables = ['conway_deathmatch']
|
25
|
+
s.add_development_dependency "buildar", "~> 2"
|
26
|
+
s.add_development_dependency "minitest", "~> 5"
|
27
|
+
s.required_ruby_version = "~> 2"
|
28
|
+
end
|
@@ -60,8 +60,8 @@ class ConwayDeathmatch::BoardState
|
|
60
60
|
(x-1..x+1).each { |xn|
|
61
61
|
next if outer_ring and !xn.between?(0, @x_len - 1)
|
62
62
|
(y-1..y+1).each { |yn|
|
63
|
-
next if outer_ring and !yn.between?(0, @y_len - 1)
|
64
|
-
|
63
|
+
next if (outer_ring and !yn.between?(0, @y_len - 1)) or
|
64
|
+
(xn == x and yn == y)
|
65
65
|
neighbors[@state[xn][yn]] += 1
|
66
66
|
}
|
67
67
|
}
|
@@ -85,8 +85,7 @@ class ConwayDeathmatch::BoardState
|
|
85
85
|
else
|
86
86
|
count = 0
|
87
87
|
neighbor_population(x, y).each { |sym, cnt|
|
88
|
-
|
89
|
-
count += cnt
|
88
|
+
count += cnt unless sym == DEAD
|
90
89
|
}
|
91
90
|
[count, ALIVE]
|
92
91
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/benchmark'
|
3
|
+
|
4
|
+
require 'conway_deathmatch'
|
5
|
+
|
6
|
+
include ConwayDeathmatch
|
7
|
+
|
8
|
+
BENCH_NEW_THRESH = (ENV['BENCH_NEW_THRESH'] || 0.9).to_f
|
9
|
+
BENCH_TICK_THRESH = (ENV['BENCH_TICK_THRESH'] || 0.9995).to_f
|
10
|
+
|
11
|
+
describe "BoardState.new Benchmark" do
|
12
|
+
bench_range do
|
13
|
+
bench_exp 9, 9999, 3
|
14
|
+
end
|
15
|
+
|
16
|
+
bench_performance_linear "width*height", BENCH_NEW_THRESH do |n|
|
17
|
+
BoardState.new(n, n)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "BoardState#tick Benchmark" do
|
22
|
+
bench_range do
|
23
|
+
bench_exp 1, 100, 3
|
24
|
+
end
|
25
|
+
|
26
|
+
bench_performance_linear "acorn demo", BENCH_TICK_THRESH do |n|
|
27
|
+
b = BoardState.new(70, 40)
|
28
|
+
Shapes.add(b, "acorn 50 18")
|
29
|
+
n.times { b.tick }
|
30
|
+
end
|
31
|
+
end
|
data/test/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'conway_deathmatch'
|
4
|
+
|
5
|
+
include ConwayDeathmatch
|
6
|
+
|
7
|
+
DEAD = BoardState::DEAD
|
8
|
+
ALIVE = BoardState::ALIVE
|
9
|
+
|
10
|
+
SHAPE = "acorn"
|
11
|
+
SHAPE_STR = "#{SHAPE} 0 0"
|
12
|
+
POINTS_COUNT = 7
|
13
|
+
SHAPE_TICK_POINTS = [
|
14
|
+
[0, 1],
|
15
|
+
[1, 1],
|
16
|
+
[2, 1],
|
17
|
+
[4, 1],
|
18
|
+
[4, 2],
|
19
|
+
[5, 1],
|
20
|
+
[5, 2],
|
21
|
+
[5, 3],
|
22
|
+
]
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
describe BoardState do
|
4
|
+
describe "an empty board" do
|
5
|
+
before do
|
6
|
+
@x = 5
|
7
|
+
@y = 5
|
8
|
+
@board = BoardState.new(@x, @y)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "must have dead population" do
|
12
|
+
@board.population[DEAD].must_equal @x * @y
|
13
|
+
@board.population.keys.length.must_equal 1
|
14
|
+
end
|
15
|
+
|
16
|
+
it "must still be dead after a tick" do
|
17
|
+
@board.tick.population[DEAD].must_equal @x*@y
|
18
|
+
@board.population.keys.length.must_equal 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it "must accept a block" do
|
22
|
+
@board.populate 1,1
|
23
|
+
@board.populate 1,2
|
24
|
+
@board.populate 2,1
|
25
|
+
@board.populate 2,2
|
26
|
+
|
27
|
+
@board.population[DEAD].must_equal @x * @y - 4
|
28
|
+
@board.population[ALIVE].must_equal 4
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "adding shapes" do
|
33
|
+
before do
|
34
|
+
@board = BoardState.new(40, 40)
|
35
|
+
Shapes.add(@board, SHAPE_STR)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "must recognize \"#{SHAPE_STR}\"" do
|
39
|
+
Shapes.known.fetch(SHAPE).each { |xy_ary|
|
40
|
+
@board.value(*xy_ary).must_equal ALIVE
|
41
|
+
}
|
42
|
+
@board.population.fetch(ALIVE).must_equal POINTS_COUNT
|
43
|
+
end
|
44
|
+
|
45
|
+
it "must tick correctly" do
|
46
|
+
@board.tick
|
47
|
+
SHAPE_TICK_POINTS.each { |xy_ary|
|
48
|
+
@board.value(*xy_ary).must_equal ALIVE
|
49
|
+
}
|
50
|
+
@board.population.fetch(ALIVE).must_equal SHAPE_TICK_POINTS.length
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/test/test_shapes.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
describe Shapes do
|
4
|
+
it "must recognize #{SHAPE}" do
|
5
|
+
Shapes.known.fetch(SHAPE).must_be_instance_of Array
|
6
|
+
end
|
7
|
+
|
8
|
+
it "must confirm #{SHAPE} on the board" do
|
9
|
+
@board = BoardState.new(20, 20)
|
10
|
+
Shapes.add(@board, SHAPE_STR)
|
11
|
+
Shapes.known.fetch(SHAPE).each { |xy_ary|
|
12
|
+
@board.value(*xy_ary).must_equal ALIVE
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conway_deathmatch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.2.
|
4
|
+
version: 0.3.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Hull
|
@@ -45,11 +45,19 @@ executables:
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
48
51
|
- bin/conway_deathmatch
|
52
|
+
- conway_deathmatch.gemspec
|
49
53
|
- lib/conway_deathmatch.rb
|
50
54
|
- lib/conway_deathmatch/board_state.rb
|
51
55
|
- lib/conway_deathmatch/data/shapes.yaml
|
52
56
|
- lib/conway_deathmatch/shapes.rb
|
57
|
+
- test/bench_board_state.rb
|
58
|
+
- test/spec_helper.rb
|
59
|
+
- test/test_board_state.rb
|
60
|
+
- test/test_shapes.rb
|
53
61
|
homepage: https://github.com/rickhull/conway_deathmatch
|
54
62
|
licenses:
|
55
63
|
- GPL
|
@@ -60,7 +68,7 @@ require_paths:
|
|
60
68
|
- lib
|
61
69
|
required_ruby_version: !ruby/object:Gem::Requirement
|
62
70
|
requirements:
|
63
|
-
- - "
|
71
|
+
- - "~>"
|
64
72
|
- !ruby/object:Gem::Version
|
65
73
|
version: '2'
|
66
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|