golr 0.5.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.
- data/bin/golr +46 -0
- data/lib/golr.rb +4 -0
- data/lib/golr/game.rb +76 -0
- data/lib/golr/game_printer.rb +31 -0
- data/lib/golr/game_reader.rb +39 -0
- data/lib/golr/key.rb +16 -0
- data/lib/golr/rules.rb +9 -0
- data/lib/golr/version.rb +3 -0
- metadata +104 -0
data/bin/golr
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'golr'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = { :generations => 100 }
|
7
|
+
|
8
|
+
optparse = OptionParser.new do |opts|
|
9
|
+
opts.banner =
|
10
|
+
"\nUsage: golr game-file [options]\n\nValid options are\n"
|
11
|
+
|
12
|
+
opts.on("-h", "--help", "Print this help") do |h|
|
13
|
+
puts opts.banner
|
14
|
+
puts opts.summarize
|
15
|
+
puts "\n"
|
16
|
+
exit 0
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-g", "--generations [NUMBER]", "Evolve game through this many generations [defaults to 100]") do |g|
|
20
|
+
options[:generations] = g.to_i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
optparse.parse!
|
25
|
+
|
26
|
+
# load game from file
|
27
|
+
game_file = ARGV[0]
|
28
|
+
begin
|
29
|
+
game_string = File.read(game_file)
|
30
|
+
game = Golr::GameReader.from_string(game_string)
|
31
|
+
rescue Errno::ENOENT, Errno::EACCES => e
|
32
|
+
puts "Cannot read #{game_file} - Does it exist and is it readable?"
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
|
36
|
+
# evolve through generations
|
37
|
+
generations = options[:generations]
|
38
|
+
puts 'Generation #0'
|
39
|
+
Golr::GamePrinter.print(game)
|
40
|
+
generation = 1
|
41
|
+
generations.times.each do
|
42
|
+
game.evolve
|
43
|
+
puts "Generation \##{generation}"
|
44
|
+
Golr::GamePrinter.print(game)
|
45
|
+
generation += 1
|
46
|
+
end
|
data/lib/golr.rb
ADDED
data/lib/golr/game.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'golr/key'
|
2
|
+
require 'golr/rules'
|
3
|
+
|
4
|
+
module Golr
|
5
|
+
|
6
|
+
class Game
|
7
|
+
|
8
|
+
attr_reader :grid, :columns, :rows
|
9
|
+
|
10
|
+
def initialize(columns, rows, living_cells = [])
|
11
|
+
@columns = columns
|
12
|
+
@rows = rows
|
13
|
+
@grid = init_grid(living_cells)
|
14
|
+
@rules = Rules.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def init_grid(living_cells = [])
|
18
|
+
new_grid = {}
|
19
|
+
Range.new(1, @columns).to_a.each do |x|
|
20
|
+
Range.new(1, @rows).to_a.each do |y|
|
21
|
+
key = Key.key(x, y)
|
22
|
+
new_grid[key] = living_cells.include?(key) ? true : false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
new_grid
|
26
|
+
end
|
27
|
+
private :init_grid
|
28
|
+
|
29
|
+
def evolve
|
30
|
+
next_grid = init_grid
|
31
|
+
@grid.each_key do |key|
|
32
|
+
next_grid[key] = @rules.evaluate(living_neighbors(key), alive?(key))
|
33
|
+
end
|
34
|
+
@grid = next_grid
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def alive?(key)
|
39
|
+
@grid[key] == true
|
40
|
+
end
|
41
|
+
|
42
|
+
def living_neighbors(key)
|
43
|
+
living_neighbors = neighboring_keys(key).inject(0) do |result, _key|
|
44
|
+
folded_key = fold_key_if_required(_key)
|
45
|
+
result += 1 if alive?(folded_key)
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
private :living_neighbors
|
50
|
+
|
51
|
+
def neighboring_keys(key)
|
52
|
+
neighbor_keys = []
|
53
|
+
x,y = Key.coordinates(key)
|
54
|
+
((x-1)..(x+1)).to_a.each do |_x|
|
55
|
+
((y-1)..(y+1)).to_a.each do |_y|
|
56
|
+
neighbor_keys << Key.key(_x,_y) unless x == _x && y == _y
|
57
|
+
end
|
58
|
+
end
|
59
|
+
neighbor_keys
|
60
|
+
end
|
61
|
+
private :neighboring_keys
|
62
|
+
|
63
|
+
# FIXME: smelly
|
64
|
+
def fold_key_if_required(key)
|
65
|
+
x,y = Key.coordinates(key)
|
66
|
+
_x = x < 1 ? @columns : x
|
67
|
+
_x = _x > @columns ? 1 : _x
|
68
|
+
_y = y < 1 ? @rows : y
|
69
|
+
_y = _y > @rows ? 1 : _y
|
70
|
+
Key.key(_x,_y)
|
71
|
+
end
|
72
|
+
private :fold_key_if_required
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Golr
|
2
|
+
|
3
|
+
class GamePrinter
|
4
|
+
|
5
|
+
def self.print(game, io = STDOUT)
|
6
|
+
line_feed(io)
|
7
|
+
print_game_state(game, io)
|
8
|
+
line_feed(io)
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def self.line_feed(io)
|
15
|
+
printf(io, "\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.print_game_state(game, io)
|
19
|
+
Range.new(1, game.rows).to_a.each do |y|
|
20
|
+
printf(io, '|')
|
21
|
+
Range.new(1, game.columns).to_a.each do |x|
|
22
|
+
printf(io, game.grid[Key.key(x,y)] == true ? 'o' : ' ')
|
23
|
+
end
|
24
|
+
printf(io, '|')
|
25
|
+
line_feed(io)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Golr
|
2
|
+
|
3
|
+
class GameReader
|
4
|
+
|
5
|
+
def self.from_string(multi_line_string)
|
6
|
+
keys = []
|
7
|
+
row = 1
|
8
|
+
columns = count_columns(multi_line_string)
|
9
|
+
multi_line_string.split(/\r?\n/).each do |line|
|
10
|
+
keys |= keys_from_line(line, row)
|
11
|
+
row += 1
|
12
|
+
end
|
13
|
+
rows = row - 1
|
14
|
+
Game.new(columns, rows, keys)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def self.count_columns(multi_line_string)
|
20
|
+
first_line = multi_line_string.split(/\r\n?|\n/).first
|
21
|
+
first_line.strip.bytesize - 2
|
22
|
+
# TODO: not entirely clear why this works even on Travis, while string.size did not
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.keys_from_line(line, row)
|
26
|
+
char_in_line = 1
|
27
|
+
keys_in_line = []
|
28
|
+
line.strip!
|
29
|
+
line.gsub!('|','')
|
30
|
+
line.each_char do |c|
|
31
|
+
keys_in_line << Key.key(char_in_line, row) if c == 'o'
|
32
|
+
char_in_line += 1
|
33
|
+
end
|
34
|
+
keys_in_line
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/golr/key.rb
ADDED
data/lib/golr/rules.rb
ADDED
data/lib/golr/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: golr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Markus Krogemann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.13.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.13.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: cucumber
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.2.3
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.2.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: simplecov
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.7.1
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.1
|
62
|
+
description: Offers methods to initialize and evolve a grid of cells, implementing
|
63
|
+
the rules of Conway's Game of Life
|
64
|
+
email:
|
65
|
+
- markus@krogemann.de
|
66
|
+
executables:
|
67
|
+
- golr
|
68
|
+
extensions: []
|
69
|
+
extra_rdoc_files: []
|
70
|
+
files:
|
71
|
+
- lib/golr/game.rb
|
72
|
+
- lib/golr/game_printer.rb
|
73
|
+
- lib/golr/game_reader.rb
|
74
|
+
- lib/golr/key.rb
|
75
|
+
- lib/golr/rules.rb
|
76
|
+
- lib/golr/version.rb
|
77
|
+
- lib/golr.rb
|
78
|
+
- bin/golr
|
79
|
+
homepage: https://github.com/mkrogemann/golr
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.8.25
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Conway's Game of Life
|
104
|
+
test_files: []
|