conway_deathmatch 0.3.2.5 → 0.3.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c2b0b7a5f1a97dd224542429ceb5d288e61ed2f
4
- data.tar.gz: 77d40e41599218e8e315a4661e77e37130a7187a
3
+ metadata.gz: 37240d180a9787a7ded00f4eaed8fb4e76ae3e39
4
+ data.tar.gz: 382b541b24dfac1f0a2cbd4ba76a576922ed7aa8
5
5
  SHA512:
6
- metadata.gz: 5686348c544509c2843456d23e3f296a77e38dd66705851b916a2998cc86e01bcf3310c7f3e86a4642e8a7bb47b8e20ecf2419b296068f6f125ad270e4195be1
7
- data.tar.gz: d56b0a39e7a10760eef7abb8a13e6da5a24af3f3080def4e58d9c9bbafc3990a7be5e257d0d4487d967aabd7d53f82af682a918e0e24a1784c4594e69557fbe4
6
+ metadata.gz: 294b292a4b0442a39e213ee17661c5247969b334da9851999f4b5a770c1a95e68f22f800702950cb5da706def0082c0358ebf34ef6d180262c27ea0261ceb3fc
7
+ data.tar.gz: 3cf35cc4f6490da0d3f6dfaf55f05ad626bc9906e8533960056a049a158801310bb9df1ccc0665107a7b9d6590ade13b27e38bfb80457370142d106b95542e97
data/README.md CHANGED
@@ -23,7 +23,7 @@ for space and population.
23
23
  This project exists not to compete with CGOLTW but as a supplementary
24
24
  project for exploration and learning. My initial motivation was to make a
25
25
  "proving ground" for searching for simple shapes and patterns with high birth
26
- rates for determining successful CGOLTW strategies.
26
+ rates for determining successful CGOLTW strategies.
27
27
 
28
28
  Usage
29
29
  ===
@@ -44,14 +44,14 @@ Demo
44
44
 
45
45
  # defaults to 70x40 board and an acorn shape
46
46
  conway_deathmatch
47
-
47
+
48
48
  # multiplayer
49
49
  conway_deathmatch --one "acorn 30 30" --two "die_hard 20 10"
50
50
 
51
51
  Available Shapes
52
52
  ---
53
53
 
54
- [Definitions](https://github.com/rickhull/conway_deathmatch/blob/master/lib/conway_deathmatch/data/shapes.yaml)
54
+ [Definitions](https://github.com/rickhull/conway_deathmatch/blob/master/lib/conway_deathmatch/shapes/classic.yaml)
55
55
 
56
56
  * acorn
57
57
  * beacon
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2.5
1
+ 0.3.3.1
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'slop'
4
+ require 'conway_deathmatch'
5
+
6
+ # process cmdline options
7
+ #
8
+ opts = Slop.parse(help: true,
9
+ banner: true,
10
+ strict: true,
11
+ optional_arguments: true) do
12
+ banner 'Usage: proving_ground [options]'
13
+
14
+ on 'w', 'width=', '[int] Board width', as: Integer
15
+ on 'height=', '[int] Board height', as: Integer
16
+ on 'n', 'num_ticks=', '[int] Max number of ticks to generate', as: Integer
17
+ on 'silent', 'Only render the final state'
18
+ on 'p', 'num_points=', '[int] Number of points to generate', as: Integer
19
+ on 'm', 'max_collisions=', '[int] Max number of collisions', as: Integer
20
+ end
21
+
22
+ width = opts[:width] || 40
23
+ height = opts[:height] || 40
24
+ n = opts[:num_ticks] || 40
25
+ p = opts[:num_points] || 5
26
+ max_c = opts[:max_collisions] || p ** 2
27
+
28
+ # answers / output
29
+ pop_final = 0
30
+ pop_final_points = []
31
+ pop_peak = 0
32
+ pop_peak_points = []
33
+ top_score = 0
34
+ top_score_points = []
35
+
36
+ def conclude!(final, final_points,
37
+ peak, peak_points,
38
+ score, score_points,
39
+ w, h)
40
+ puts
41
+ puts "final: #{final}"
42
+ puts "final_points: #{final_points}"
43
+ puts "shape_str: #{shape_str(final_points)}"
44
+ puts
45
+ puts "peak: #{peak}"
46
+ puts "peak_points: #{peak_points}"
47
+ puts "shape_str: #{shape_str(peak_points)}"
48
+ puts
49
+ puts "score: #{score}"
50
+ puts "score_points: #{score_points}"
51
+ puts "shape_str: #{shape_str(score_points)}"
52
+
53
+ exit 0
54
+ end
55
+
56
+ # choose center point
57
+ # choose next point within 2 units randomly
58
+ def generate_points(num_points, width, height)
59
+ points = [[width / 2, height / 2]]
60
+ count = 0
61
+ while points.length < num_points
62
+ raise("sanity check failed") if count > num_points * 2
63
+ count += 1
64
+ next_p = next_point(points.sample)
65
+ if next_p[0].between?(0, width - 1) and next_p[1].between?(0, height - 1)
66
+ points << next_p unless points.include?(next_p)
67
+ else
68
+ # debug
69
+ puts "#{next_p.inspect} out of bounds"
70
+ end
71
+ end
72
+ points
73
+ end
74
+
75
+ def next_point(prev_point)
76
+ prev_point.map { |dim| random_within(dim, 2) }
77
+ end
78
+
79
+ def random_within(x, dist)
80
+ new_x = x - dist + rand(dist * 2)
81
+ new_x += 1 if new_x >= x
82
+ new_x
83
+ end
84
+
85
+ def shape_str(points)
86
+ points.map { |point| "p #{point[0]} #{point[1]}" }.join(' ')
87
+ end
88
+
89
+ Signal.trap("INT") do
90
+ conclude!(pop_final, pop_final_points,
91
+ pop_peak, pop_peak_points,
92
+ top_score, top_score_points,
93
+ width, height)
94
+ end
95
+
96
+ include ConwayDeathmatch
97
+ ALIVE = BoardState::ALIVE
98
+ SEEN = {}
99
+ collisions = 0
100
+
101
+ loop {
102
+ # populate new board with random points
103
+ #
104
+ b = BoardState.new(width, height)
105
+ points = generate_points(p, width, height)
106
+
107
+ # have we seen these points before?
108
+ #
109
+ if SEEN[points]
110
+ collisions += 1
111
+ puts "X" * collisions
112
+ break if collisions > max_c
113
+ next
114
+ else
115
+ SEEN[points] = true
116
+ end
117
+ b.add_points(points)
118
+
119
+ # establish vars outside block
120
+ #
121
+ pop = nil
122
+ peak = 0
123
+ static_cnt = 0
124
+ score = 0
125
+ ticks = 0
126
+
127
+ # tick and track population
128
+ #
129
+ n.times { |i|
130
+ b.tick
131
+ ticks += 1
132
+
133
+ # evaluate board
134
+ #
135
+ last_pop = pop
136
+ pop = b.population[ALIVE] || 0
137
+ score += ticks * pop
138
+ peak = pop if pop > peak
139
+
140
+ # short-circuit static or (soon-to-be) empty boards
141
+ #
142
+ break if pop < 3
143
+ static_cnt = (pop == last_pop ? static_cnt + 1 : 0)
144
+ break if static_cnt > 3
145
+ }
146
+
147
+ puts "#{pop} (#{peak}) [#{score}]"
148
+
149
+ # track the highest populators
150
+ #
151
+ if pop > pop_final
152
+ pop_final = pop
153
+ pop_final_points = points
154
+ puts "\tLargest final: #{pop_final}"
155
+ end
156
+
157
+ if peak > pop_peak
158
+ pop_peak = peak
159
+ pop_peak_points = points
160
+ puts "\tLargest peak: #{pop_peak}"
161
+ end
162
+
163
+ if score > top_score
164
+ top_score = score
165
+ top_score_points = points
166
+ puts "\tLargest score: #{top_score}"
167
+ end
168
+ }
169
+
170
+ conclude!(pop_final, pop_final_points,
171
+ pop_peak, pop_peak_points,
172
+ top_score, top_score_points,
173
+ width, height)
@@ -14,8 +14,10 @@ Gem::Specification.new do |s|
14
14
  'lib/conway_deathmatch.rb',
15
15
  'lib/conway_deathmatch/board_state.rb',
16
16
  'lib/conway_deathmatch/shapes.rb',
17
- 'lib/conway_deathmatch/data/shapes.yaml',
17
+ 'lib/conway_deathmatch/shapes/classic.yaml',
18
+ 'lib/conway_deathmatch/shapes/discovered.yaml',
18
19
  'bin/conway_deathmatch',
20
+ 'bin/proving_ground',
19
21
  'test/bench_board_state.rb',
20
22
  'test/spec_helper.rb',
21
23
  'test/test_board_state.rb',
@@ -0,0 +1,85 @@
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
+ a7:
61
+ - [0, 3]
62
+ - [1, 4]
63
+ - [1, 1]
64
+ - [2, 0]
65
+ - [2, 1]
66
+ - [3, 2]
67
+ - [4, 1]
68
+
69
+ b7: # rocket
70
+ - [0, 0]
71
+ - [0, 1]
72
+ - [0, 2]
73
+ - [1, 3]
74
+ - [2, 0]
75
+ - [2, 1]
76
+ - [2, 2]
77
+
78
+ c7: # urawizardarry
79
+ - [0, 0]
80
+ - [1, 1]
81
+ - [2, 2]
82
+ - [3, 2]
83
+ - [4, 3]
84
+ - [5, 4]
85
+ - [5, 5]
@@ -2,9 +2,18 @@ require 'conway_deathmatch/board_state'
2
2
  require 'yaml'
3
3
 
4
4
  module ConwayDeathmatch::Shapes
5
- # memoize data/shapes.yaml
6
- def self.known
7
- @@known ||= YAML.load_file(File.join(__dir__, 'data', 'shapes.yaml'))
5
+ def self.load_yaml(filename)
6
+ YAML.load_file(File.join(__dir__, 'shapes', filename))
7
+ end
8
+
9
+ # memoize shapes/classic.yaml
10
+ def self.classic
11
+ @@classic ||= self.load_yaml('classic.yaml')
12
+ end
13
+
14
+ # memoize shapes/discovered.yaml
15
+ def self.discovered
16
+ @@disovered ||= self.load_yaml('discovered.yaml')
8
17
  end
9
18
 
10
19
  # parse a string like "acorn 12 22 block 5 0 p 1 2 p 3 4 p 56 78"
@@ -12,8 +21,8 @@ module ConwayDeathmatch::Shapes
12
21
  def self.add(board, str, val = BoardState::ALIVE)
13
22
  tokens = str.split
14
23
  points = []
15
- known = self.known
16
-
24
+ classic = self.classic
25
+
17
26
  while !tokens.empty?
18
27
  shape = tokens.shift.downcase
19
28
  raise "no coordinates for #{shape}" if tokens.length < 2
@@ -23,7 +32,8 @@ module ConwayDeathmatch::Shapes
23
32
  when 'p'
24
33
  points << [x, y]
25
34
  else
26
- board.add_points(known.fetch(shape), x, y, val)
35
+ found = classic[shape] || self.discovered.fetch(shape)
36
+ board.add_points(found, x, y, val)
27
37
  end
28
38
  end
29
39
  board.add_points(points, 0, 0, val)
@@ -28,4 +28,12 @@ describe "BoardState#tick Benchmark" do
28
28
  Shapes.add(b, "acorn 50 18")
29
29
  n.times { b.tick }
30
30
  end
31
+
32
+ bench_performance_linear "multiplayer demo", BENCH_TICK_THRESH do |n|
33
+ b = BoardState.new(70, 40)
34
+ b.multiplayer = true
35
+ Shapes.add(b, "acorn 30 30", "1")
36
+ Shapes.add(b, "die_hard 20 10", "2")
37
+ n.times { b.tick }
38
+ end
31
39
  end
@@ -36,7 +36,7 @@ describe BoardState do
36
36
  end
37
37
 
38
38
  it "must recognize \"#{SHAPE_STR}\"" do
39
- Shapes.known.fetch(SHAPE).each { |xy_ary|
39
+ Shapes.classic.fetch(SHAPE).each { |xy_ary|
40
40
  @board.value(*xy_ary).must_equal ALIVE
41
41
  }
42
42
  @board.population.fetch(ALIVE).must_equal POINTS_COUNT
data/test/test_shapes.rb CHANGED
@@ -2,13 +2,13 @@ require_relative './spec_helper'
2
2
 
3
3
  describe Shapes do
4
4
  it "must recognize #{SHAPE}" do
5
- Shapes.known.fetch(SHAPE).must_be_instance_of Array
5
+ Shapes.classic.fetch(SHAPE).must_be_instance_of Array
6
6
  end
7
7
 
8
8
  it "must confirm #{SHAPE} on the board" do
9
9
  @board = BoardState.new(20, 20)
10
10
  Shapes.add(@board, SHAPE_STR)
11
- Shapes.known.fetch(SHAPE).each { |xy_ary|
11
+ Shapes.classic.fetch(SHAPE).each { |xy_ary|
12
12
  @board.value(*xy_ary).must_equal ALIVE
13
13
  }
14
14
  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.3.2.5
4
+ version: 0.3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Hull
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-04 00:00:00.000000000 Z
11
+ date: 2014-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: buildar
@@ -49,11 +49,13 @@ files:
49
49
  - Rakefile
50
50
  - VERSION
51
51
  - bin/conway_deathmatch
52
+ - bin/proving_ground
52
53
  - conway_deathmatch.gemspec
53
54
  - lib/conway_deathmatch.rb
54
55
  - lib/conway_deathmatch/board_state.rb
55
- - lib/conway_deathmatch/data/shapes.yaml
56
56
  - lib/conway_deathmatch/shapes.rb
57
+ - lib/conway_deathmatch/shapes/classic.yaml
58
+ - lib/conway_deathmatch/shapes/discovered.yaml
57
59
  - test/bench_board_state.rb
58
60
  - test/spec_helper.rb
59
61
  - test/test_board_state.rb