cellular_automata 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Rakefile +3 -0
- data/bin/cell_console +17 -0
- data/bin/cell_gif +52 -0
- data/cellular_automata.gemspec +13 -10
- data/ext/cellular_c/cellular_c.c +76 -0
- data/ext/cellular_c/extconf.rb +6 -0
- data/lib/cellular_automata/board.rb +32 -27
- data/lib/cellular_automata/gif_writer.rb +56 -0
- data/lib/cellular_automata/gui_window.rb +12 -3
- data/lib/cellular_automata/rule.rb +12 -15
- data/lib/cellular_automata/version.rb +1 -1
- data/lib/cellular_automata.rb +3 -0
- metadata +44 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0237b3c22f9d23179fc50a5c88bc5217ce95025e
|
4
|
+
data.tar.gz: 93bcb9d782c3ec0643fdee8b9e04d0de01c62a3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0ae054a68622f16753da6ca3968a20c64af2ea6af76a342a5223f10f435553cc71be98315f607b92f159cf7e29eb435411253f5a626dc13e96d9ba8855ab8f9
|
7
|
+
data.tar.gz: dc06e35c815e74eeed6ba5048f352410937d8b51e67d827d7f7b3112c83cc087d3196f5910e357900fd61693d1f9227734cb316652be05de7c3fabe0f976acd7
|
data/.gitignore
CHANGED
data/Rakefile
CHANGED
data/bin/cell_console
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'cellular_automata'
|
4
|
+
require 'optparse'
|
5
|
+
require 'byebug'
|
6
|
+
require 'pry'
|
7
|
+
|
8
|
+
width = 120
|
9
|
+
height = 30
|
10
|
+
rule = 'B3S2'
|
11
|
+
board = CellularAutomata::Board.new(width: width, height: height, rule: rule)
|
12
|
+
board.tick!
|
13
|
+
board.tick!
|
14
|
+
puts board.to_s
|
15
|
+
state = board.state
|
16
|
+
binding.pry
|
17
|
+
exit
|
data/bin/cell_gif
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'cellular_automata'
|
4
|
+
require 'optparse'
|
5
|
+
require 'gosu'
|
6
|
+
|
7
|
+
def opts_from_cli
|
8
|
+
options = {}
|
9
|
+
opt_parser = OptionParser.new do |opts|
|
10
|
+
opts.program_name = File.basename(__FILE__)
|
11
|
+
opts.banner = "#{opts.program_name} [options] RULE"
|
12
|
+
opts.on('-w WIDTH', '--width WIDTH', 'Set width') { |w| options[:width] = w.to_i }
|
13
|
+
opts.on('-h HEIGHT', '--height HEIGHT', 'Set height') { |h| options[:height] = h.to_i }
|
14
|
+
opts.on('-s SCALE', '--scale SCALE', 'Factor by which to scale game board') { |s| options[:scale] = s.to_i }
|
15
|
+
opts.on('-c WIDTH', '--cell-width WIDTH', 'Factor by which to scale cells', 'Use 1 for an \'LED\' look',
|
16
|
+
'Use 2 for no borders around cells', 'or choose anything in between') {|w| options[:cell_scale] = w.to_f }
|
17
|
+
opts.on('-f FRAMES', '--frames FRAMES', 'Number of frames to write') { |f| options[:frames] = f.to_i }
|
18
|
+
opts.on('-v', '--version', 'Print version information') do
|
19
|
+
puts "#{File.basename(__FILE__)} #{CellularAutomata::VERSION}"
|
20
|
+
exit true
|
21
|
+
end
|
22
|
+
opts.on('--help', 'Display this screen') do
|
23
|
+
puts opts
|
24
|
+
exit true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
begin
|
28
|
+
opt_parser.parse!
|
29
|
+
rescue OptionParser::InvalidOption => e
|
30
|
+
puts e.message
|
31
|
+
exit false
|
32
|
+
end
|
33
|
+
options
|
34
|
+
end
|
35
|
+
|
36
|
+
opts = opts_from_cli
|
37
|
+
opts[:width] ||= 160
|
38
|
+
opts[:height] ||= 120
|
39
|
+
opts[:scale] ||= 1
|
40
|
+
opts[:cell_scale] ||= 2.0
|
41
|
+
opts[:cell_scale] = 2.0 if opts[:cell_scale] > 2.0
|
42
|
+
opts[:cell_scale] = 1.0 if opts[:cell_scale] < 1.0
|
43
|
+
opts[:frames] ||= 100
|
44
|
+
rule = ARGV[0] || 'B3S2'
|
45
|
+
opts[:rule] = rule
|
46
|
+
|
47
|
+
trap 'SIGINT' do
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
CellularAutomata::GifWriter.write(opts)
|
52
|
+
exit
|
data/cellular_automata.gemspec
CHANGED
@@ -4,26 +4,29 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'cellular_automata/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = "cellular_automata"
|
8
8
|
spec.version = CellularAutomata::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ["Forrest Fleming"]
|
10
|
+
spec.email = ["ffleming@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{A simulation of cellular automata}
|
13
13
|
spec.description = %q{A set of 0-player games, of which Conway's Game of Life is a member.}
|
14
|
-
spec.homepage =
|
14
|
+
spec.homepage = "https://github.com/ffleming/cellular_automata"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
-
spec.bindir =
|
17
|
+
spec.bindir = "bin"
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.license = 'MIT'
|
22
22
|
|
23
|
-
spec.
|
24
|
-
|
25
|
-
spec.
|
26
|
-
spec.
|
23
|
+
spec.extensions << 'ext/cellular_c/extconf.rb'
|
24
|
+
|
25
|
+
spec.add_runtime_dependency "gosu", '~> 0', '>= 0.9'
|
26
|
+
spec.add_runtime_dependency "rmagick", '~> 2', '>= 2.15'
|
27
|
+
spec.add_development_dependency "bundler", "~> 1", ">= 1.8"
|
28
|
+
spec.add_development_dependency "rake-compiler", '~> 0', '>= 0.9'
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
30
|
spec.add_development_dependency 'pry', '~> 0.10'
|
28
31
|
spec.add_development_dependency 'byebug', '~> 4'
|
29
32
|
spec.add_development_dependency 'pry-byebug', '~> 3.1'
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
|
4
|
+
VALUE CellularC = Qnil;
|
5
|
+
void Init_cellular_c();
|
6
|
+
int cell_value(VALUE, int);
|
7
|
+
int neighbor_population_of(VALUE, int, int);
|
8
|
+
VALUE method_dup_state(VALUE, VALUE);
|
9
|
+
VALUE method_next_state(VALUE, VALUE, VALUE);
|
10
|
+
|
11
|
+
void Init_cellular_c() {
|
12
|
+
CellularC = rb_define_module("CellularC");
|
13
|
+
rb_define_singleton_method(CellularC, "dup_state", method_dup_state, 1);
|
14
|
+
rb_define_singleton_method(CellularC, "next_state", method_next_state, 2);
|
15
|
+
}
|
16
|
+
|
17
|
+
int cell_value(VALUE rule, int num_neighbors) {
|
18
|
+
VALUE rule_array = rb_iv_get(rule, "@rule_array");
|
19
|
+
VALUE result = rb_ary_entry(rule_array, num_neighbors);
|
20
|
+
VALUE live = ID2SYM(rb_intern("birth"));
|
21
|
+
VALUE die = ID2SYM(rb_intern("die"));
|
22
|
+
if(result == die) {
|
23
|
+
return 0;
|
24
|
+
} else if(result == live) {
|
25
|
+
return 1;
|
26
|
+
}
|
27
|
+
return -1;
|
28
|
+
}
|
29
|
+
|
30
|
+
int neighbor_population_of(VALUE state, int x, int y) {
|
31
|
+
int height = (int)RARRAY_LEN(state);
|
32
|
+
int width = (int)RARRAY_LEN(rb_ary_entry(state, 0));
|
33
|
+
int min_x = x > 1 ? x - 1 : 0;
|
34
|
+
int max_x = x < width - 2 ? x + 1 : width - 1;
|
35
|
+
int min_y = y > 1 ? y - 1 : 0;
|
36
|
+
int max_y = y < height - 2 ? y + 1 : height - 1;
|
37
|
+
int ret = 0;
|
38
|
+
|
39
|
+
for(int row = min_y; row <= max_y; row++) {
|
40
|
+
VALUE row_array = rb_ary_entry(state, row);
|
41
|
+
for(int col = min_x; col <= max_x; col++) {
|
42
|
+
int alive = FIX2INT(rb_ary_entry(row_array, col));
|
43
|
+
if((alive == 1) && ((x != col) || (y != row))) {
|
44
|
+
ret += 1;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
return ret;
|
49
|
+
}
|
50
|
+
|
51
|
+
VALUE method_next_state(VALUE self, VALUE state, VALUE rule) {
|
52
|
+
VALUE next_state = method_dup_state(self, state);
|
53
|
+
int height = (int)RARRAY_LEN(state);
|
54
|
+
int width = (int)RARRAY_LEN(rb_ary_entry(state, 0));
|
55
|
+
for(int row = 0; row < height; row++) {
|
56
|
+
VALUE row_array = rb_ary_entry(next_state, row);
|
57
|
+
for(int col = 0; col < width; col++) {
|
58
|
+
int new_value = cell_value(rule, neighbor_population_of(state, col, row));
|
59
|
+
if(new_value == -1) {
|
60
|
+
continue;
|
61
|
+
}
|
62
|
+
rb_ary_store(row_array, col, INT2FIX(new_value));
|
63
|
+
}
|
64
|
+
}
|
65
|
+
return next_state;
|
66
|
+
}
|
67
|
+
|
68
|
+
VALUE method_dup_state(VALUE self, VALUE state) {
|
69
|
+
int height = (int)RARRAY_LEN(state);
|
70
|
+
VALUE dup = rb_ary_new2(height);
|
71
|
+
for(int y = 0; y < height; y++) {
|
72
|
+
VALUE row = rb_ary_dup(rb_ary_entry(state, y));
|
73
|
+
rb_ary_push(dup, row);
|
74
|
+
}
|
75
|
+
return dup;
|
76
|
+
}
|
@@ -1,10 +1,13 @@
|
|
1
1
|
class CellularAutomata::Board
|
2
|
-
attr_reader :width, :height, :rule
|
3
|
-
def initialize(rule: 'B3S2', width: 80, height: 20)
|
2
|
+
attr_reader :width, :height, :rule, :history, :state
|
3
|
+
def initialize(rule: 'B3S2', width: 80, height: 20, max_history: 2)
|
4
4
|
@height = height
|
5
5
|
@width = width
|
6
6
|
@state = build_array
|
7
7
|
@rule = CellularAutomata::Rule.new(rule)
|
8
|
+
@history = []
|
9
|
+
@max_history = max_history
|
10
|
+
max_history.times { history.push build_array }
|
8
11
|
seed!
|
9
12
|
end
|
10
13
|
|
@@ -14,7 +17,7 @@ class CellularAutomata::Board
|
|
14
17
|
@state.each do |row|
|
15
18
|
ret << "|"
|
16
19
|
row.each do |cell|
|
17
|
-
ret << cell
|
20
|
+
ret << (cell == 0 ? ' ' : '*' )
|
18
21
|
end
|
19
22
|
ret << "|\n"
|
20
23
|
end
|
@@ -22,17 +25,24 @@ class CellularAutomata::Board
|
|
22
25
|
end
|
23
26
|
|
24
27
|
def tick!
|
25
|
-
next_state =
|
26
|
-
|
27
|
-
|
28
|
-
end
|
28
|
+
next_state = CellularC.next_state(@state, rule)
|
29
|
+
history.unshift CellularC.dup_state(@state)
|
30
|
+
history.pop if history.length > @max_history
|
29
31
|
@state = next_state
|
30
32
|
end
|
31
33
|
|
34
|
+
def kill(array: , x: , y: )
|
35
|
+
array[y][x] = 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def live(array: , x: , y: )
|
39
|
+
array[y][x] = 1
|
40
|
+
end
|
41
|
+
|
32
42
|
def each_cell
|
33
43
|
(0..height-1).each do |y|
|
34
44
|
(0..width-1).each do |x|
|
35
|
-
yield
|
45
|
+
yield(x, y)
|
36
46
|
end
|
37
47
|
end
|
38
48
|
end
|
@@ -40,7 +50,7 @@ class CellularAutomata::Board
|
|
40
50
|
private
|
41
51
|
|
42
52
|
def seed!
|
43
|
-
each_cell { |
|
53
|
+
each_cell { |x, y| @state[y][x] = 1 if rand < 0.1 }
|
44
54
|
end
|
45
55
|
|
46
56
|
def build_array
|
@@ -48,29 +58,24 @@ class CellularAutomata::Board
|
|
48
58
|
(0..height-1).each do |y|
|
49
59
|
arr[y] = []
|
50
60
|
(0..width-1).each do |x|
|
51
|
-
arr[y][x] =
|
61
|
+
arr[y][x] = 0
|
52
62
|
end
|
53
63
|
end
|
54
64
|
return arr
|
55
65
|
end
|
56
66
|
|
57
|
-
def neighbor_population_of(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
y = cell.y ; x = cell.x
|
70
|
-
[ cell_at(y-1, x-1), cell_at(y-1, x ), cell_at(y-1, x+1),
|
71
|
-
cell_at(y, x+1), cell_at(y , x-1),
|
72
|
-
cell_at(y+1, x-1), cell_at(y+1, x ), cell_at(y+1, x+1) ].compact
|
67
|
+
def neighbor_population_of(x: , y: )
|
68
|
+
ret = 0
|
69
|
+
min_x = x > 1 ? x - 1 : 0
|
70
|
+
max_x = x < width - 2 ? x + 1 : width - 1
|
71
|
+
min_y = y > 1 ? y - 1 : 0
|
72
|
+
max_y = y < height - 2 ? y + 1 : height - 1
|
73
|
+
(min_y..max_y).each do |row|
|
74
|
+
(min_x..max_x).each do |col|
|
75
|
+
ret += 1 unless ((x == col && y == row) || @state[row][col] == 0)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
ret
|
73
79
|
end
|
74
|
-
|
75
80
|
end
|
76
81
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module CellularAutomata::GifWriter
|
2
|
+
class << self
|
3
|
+
def write(opts={})
|
4
|
+
@scale = opts[:scale]
|
5
|
+
@cell_width = scale**opts[:cell_scale]
|
6
|
+
@board = CellularAutomata::Board.new(width: opts[:width]/scale, height: opts[:height]/scale, rule: opts[:rule])
|
7
|
+
@gif = Magick::ImageList.new
|
8
|
+
@width = opts[:width]
|
9
|
+
@height = opts[:height]
|
10
|
+
@frames = opts[:frames]
|
11
|
+
write_gif('test.gif')
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :board, :scale, :cell_width, :frames, :writer, :height, :width
|
17
|
+
|
18
|
+
def write_gif(outfile)
|
19
|
+
frames.times do |i|
|
20
|
+
draw_frame
|
21
|
+
board.tick!
|
22
|
+
end
|
23
|
+
@gif.write(outfile)
|
24
|
+
end
|
25
|
+
|
26
|
+
def draw_frame
|
27
|
+
writer = Magick::Draw.new
|
28
|
+
frame = Magick::Image.new(width, height) do
|
29
|
+
self.background_color = '#000000'
|
30
|
+
end
|
31
|
+
board.each_cell do |cell|
|
32
|
+
prev_1 = board.history[0][cell.y][cell.x]
|
33
|
+
prev_2 = board.history[1][cell.y][cell.x]
|
34
|
+
color = '#000000'
|
35
|
+
if cell.alive?
|
36
|
+
color = '#FFFF00'
|
37
|
+
elsif prev_1.alive?
|
38
|
+
color = '#AAAA00'
|
39
|
+
elsif prev_2.alive?
|
40
|
+
color = '#444400'
|
41
|
+
end
|
42
|
+
writer.stroke color
|
43
|
+
writer.fill color
|
44
|
+
x1 = cell.x * scale**2
|
45
|
+
y1 = cell.y * scale**2
|
46
|
+
x2 = x1 + cell_width
|
47
|
+
y2 = y1 + cell_width
|
48
|
+
writer.rectangle(x1, y1, x2, y2)
|
49
|
+
end
|
50
|
+
writer.draw(frame)
|
51
|
+
@gif << frame
|
52
|
+
print '.'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -14,9 +14,18 @@ class CellWindow < Gosu::Window
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def draw
|
17
|
-
board.each_cell do |
|
18
|
-
|
19
|
-
|
17
|
+
board.each_cell do |x, y|
|
18
|
+
prev_1 = board.history[0][y][x] == 1
|
19
|
+
prev_2 = board.history[1][y][x] == 1
|
20
|
+
color = Gosu::Color::BLACK
|
21
|
+
if board.state[y][x] == 1
|
22
|
+
color = Gosu::Color.argb(0xff_FFFF00)
|
23
|
+
elsif prev_1
|
24
|
+
color = Gosu::Color.argb(0xff_AAAA00)
|
25
|
+
elsif prev_2
|
26
|
+
color = Gosu::Color.argb(0xff_444400)
|
27
|
+
end
|
28
|
+
Gosu.draw_rect(x * scale**2, y * scale**2, cell_width, cell_width, color, 0, :default)
|
20
29
|
end
|
21
30
|
end
|
22
31
|
|
@@ -1,27 +1,24 @@
|
|
1
1
|
class CellularAutomata::Rule
|
2
2
|
def initialize(rule_string)
|
3
|
-
|
3
|
+
rules = rule_string.downcase.scan(/[bs]\d+/)
|
4
|
+
raise ArgumentError.new("Invalid rule string #{rule_string}") if rules.length != 2
|
5
|
+
birth = rules.select {|s| s.start_with?('b')}.first
|
6
|
+
survive = rules.select {|s| s.start_with?('s')}.first
|
7
|
+
@rule_array = rules_array_from birth: birth, survive: survive
|
4
8
|
end
|
5
9
|
|
6
10
|
def process(input)
|
7
|
-
return @
|
8
|
-
end
|
9
|
-
|
10
|
-
def process2(input)
|
11
|
-
@rule_hash[input] != :die!
|
11
|
+
return @rule_array[input.to_i] || raise(ArgumentError.new("I don't know what to do with #{input.class} #{input}"))
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
death = ((0..8).to_a - birth) - survive
|
23
|
-
{live!: birth, survive!: survive, die!: death}.each_with_object({}) do |(k, v), ret|
|
24
|
-
v.each {|int| ret[int] = k}
|
16
|
+
def rules_array_from(birth: , survive: )
|
17
|
+
('0'..'8').each_with_object([]) do |i_str, ret|
|
18
|
+
val = :die
|
19
|
+
val = :survive if survive.include? i_str
|
20
|
+
val = :birth if birth.include? i_str
|
21
|
+
ret << val
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
data/lib/cellular_automata.rb
CHANGED
@@ -2,11 +2,14 @@ require 'pry'
|
|
2
2
|
require 'byebug'
|
3
3
|
require 'pry-byebug'
|
4
4
|
require 'gosu'
|
5
|
+
require 'rmagick'
|
5
6
|
require "cellular_automata/version"
|
6
7
|
require "cellular_automata/cell"
|
7
8
|
require "cellular_automata/rule"
|
8
9
|
require "cellular_automata/board"
|
9
10
|
require "cellular_automata/gui_window"
|
11
|
+
require "cellular_automata/gif_writer"
|
12
|
+
require 'cellular_c.bundle'
|
10
13
|
|
11
14
|
module CellularAutomata
|
12
15
|
end
|
metadata
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cellular_automata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Forrest Fleming
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gosu
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
- - ">="
|
18
21
|
- !ruby/object:Gem::Version
|
19
22
|
version: '0.9'
|
20
23
|
type: :runtime
|
@@ -22,28 +25,31 @@ dependencies:
|
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- - ">="
|
25
31
|
- !ruby/object:Gem::Version
|
26
32
|
version: '0.9'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
34
|
+
name: rmagick
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
39
|
+
version: '2'
|
34
40
|
- - ">="
|
35
41
|
- !ruby/object:Gem::Version
|
36
|
-
version: '
|
37
|
-
type: :
|
42
|
+
version: '2.15'
|
43
|
+
type: :runtime
|
38
44
|
prerelease: false
|
39
45
|
version_requirements: !ruby/object:Gem::Requirement
|
40
46
|
requirements:
|
41
47
|
- - "~>"
|
42
48
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
49
|
+
version: '2'
|
44
50
|
- - ">="
|
45
51
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
52
|
+
version: '2.15'
|
47
53
|
- !ruby/object:Gem::Dependency
|
48
54
|
name: bundler
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,6 +70,26 @@ dependencies:
|
|
64
70
|
- - ">="
|
65
71
|
- !ruby/object:Gem::Version
|
66
72
|
version: '1.8'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: rake-compiler
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.9'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0.9'
|
67
93
|
- !ruby/object:Gem::Dependency
|
68
94
|
name: rake
|
69
95
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,8 +151,11 @@ email:
|
|
125
151
|
- ffleming@gmail.com
|
126
152
|
executables:
|
127
153
|
- cell
|
154
|
+
- cell_console
|
155
|
+
- cell_gif
|
128
156
|
- cell_gui
|
129
|
-
extensions:
|
157
|
+
extensions:
|
158
|
+
- ext/cellular_c/extconf.rb
|
130
159
|
extra_rdoc_files: []
|
131
160
|
files:
|
132
161
|
- ".gitignore"
|
@@ -136,11 +165,16 @@ files:
|
|
136
165
|
- README.md
|
137
166
|
- Rakefile
|
138
167
|
- bin/cell
|
168
|
+
- bin/cell_console
|
169
|
+
- bin/cell_gif
|
139
170
|
- bin/cell_gui
|
140
171
|
- cellular_automata.gemspec
|
172
|
+
- ext/cellular_c/cellular_c.c
|
173
|
+
- ext/cellular_c/extconf.rb
|
141
174
|
- lib/cellular_automata.rb
|
142
175
|
- lib/cellular_automata/board.rb
|
143
176
|
- lib/cellular_automata/cell.rb
|
177
|
+
- lib/cellular_automata/gif_writer.rb
|
144
178
|
- lib/cellular_automata/gui_window.rb
|
145
179
|
- lib/cellular_automata/rule.rb
|
146
180
|
- lib/cellular_automata/version.rb
|
@@ -164,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
198
|
version: '0'
|
165
199
|
requirements: []
|
166
200
|
rubyforge_project:
|
167
|
-
rubygems_version: 2.
|
201
|
+
rubygems_version: 2.4.7
|
168
202
|
signing_key:
|
169
203
|
specification_version: 4
|
170
204
|
summary: A simulation of cellular automata
|