conway_deathmatch 0.3.2.5 → 0.3.3.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
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