golr 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,4 @@
1
+ require 'golr/game'
2
+ require 'golr/game_reader'
3
+ require 'golr/game_printer'
4
+
@@ -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
@@ -0,0 +1,16 @@
1
+ module Golr
2
+
3
+ class Key
4
+
5
+ def self.key(x, y)
6
+ "#{x}_#{y}"
7
+ end
8
+
9
+ def self.coordinates(key)
10
+ split = key.split('_')
11
+ [split[0].to_i, split[1].to_i]
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,9 @@
1
+ module Golr
2
+ class Rules
3
+ def evaluate(living_neighbors, cell_alive = false)
4
+ return true if living_neighbors == 3
5
+ return true if cell_alive && living_neighbors == 2
6
+ false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Golr
2
+ VERSION = "0.5.1"
3
+ end
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: []