golr 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|