cellular_automata 0.1.2 → 0.1.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 891c6c36e259e19ad44dad69cdfef0336058978a
4
- data.tar.gz: 4e5898cdadcdc8031601e70f4da409b8157fdbb1
3
+ metadata.gz: 0237b3c22f9d23179fc50a5c88bc5217ce95025e
4
+ data.tar.gz: 93bcb9d782c3ec0643fdee8b9e04d0de01c62a3c
5
5
  SHA512:
6
- metadata.gz: 4e7ae0a28aecd0030faefaa03fefe2671ed7d0a1e477190d48506c2178d5a5e9a9322e827fa3f52b21bd4024370ffc2b6448bc8741f49b0fdc4f7a705d6d632e
7
- data.tar.gz: e59aaed8f24f32467b4c069c3df8a40e458d64cb872703f17c553933ec6a469a2b1f1696598dc7bb48dadf4425abd335f1f96929abb39cdbd9e1e2db7ec6f26a
6
+ metadata.gz: b0ae054a68622f16753da6ca3968a20c64af2ea6af76a342a5223f10f435553cc71be98315f607b92f159cf7e29eb435411253f5a626dc13e96d9ba8855ab8f9
7
+ data.tar.gz: dc06e35c815e74eeed6ba5048f352410937d8b51e67d827d7f7b3112c83cc087d3196f5910e357900fd61693d1f9227734cb316652be05de7c3fabe0f976acd7
data/.gitignore CHANGED
@@ -8,3 +8,4 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  *.gem
11
+ /lib/*.bundle
data/Rakefile CHANGED
@@ -1 +1,4 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/extensiontask'
3
+ spec = Gem::Specification.load('cellular_automata.gemspec')
4
+ Rake::ExtensionTask.new('cellular_c', spec)
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
@@ -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 = 'cellular_automata'
7
+ spec.name = "cellular_automata"
8
8
  spec.version = CellularAutomata::VERSION
9
- spec.authors = ['Forrest Fleming']
10
- spec.email = ['ffleming@gmail.com']
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 = 'https://github.com/ffleming/cellular_automata'
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 = 'bin'
17
+ spec.bindir = "bin"
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.require_paths = ['lib']
19
+ spec.require_paths = ["lib"]
20
20
 
21
21
  spec.license = 'MIT'
22
22
 
23
- spec.add_runtime_dependency 'gosu', '~> 0.9'
24
- spec.add_development_dependency 'releasy', '~> 1', '>= 1.8'
25
- spec.add_development_dependency 'bundler', '~> 1', '>= 1.8'
26
- spec.add_development_dependency 'rake', '~> 10.0'
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
+ }
@@ -0,0 +1,6 @@
1
+ # ext/extconf.rb
2
+ require 'mkmf'
3
+ extension_name = 'cellular_c'
4
+ dir_config(extension_name)
5
+ create_header
6
+ create_makefile(extension_name)
@@ -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.to_s
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 = Marshal.load(Marshal.dump @state)
26
- each_cell do |cell|
27
- next_state[cell.y][cell.x].send rule.process(neighbor_population_of cell) #= next_cell #cell.send(rule.process(adj_pop))
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 @state[y][x]
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 { |c| c.live! if rand < 0.1 }
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] = CellularAutomata::Cell.new(row: y, column: x, alive: false)
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(cell)
58
- neighbors_of(cell).select(&:alive?).length
59
- end
60
-
61
- def cell_at(y, x)
62
- return nil if x < 0 || y < 0
63
- return nil if y > @state.length-1
64
- return nil if x > @state[0].length-1
65
- return @state[y][x]
66
- end
67
-
68
- def neighbors_of(cell)
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 |cell|
18
- color = cell.alive? ? Gosu::Color::YELLOW : Gosu::Color::BLACK
19
- Gosu.draw_rect(cell.x * scale**2, cell.y * scale**2, cell_width, cell_width, color, 0, :default)
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
- @rule_hash = process_rule! rule_string
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 @rule_hash[input] || raise(ArgumentError.new("I don't know what to do with #{input.class} #{input}"))
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 process_rule!(rule_string)
17
- rules = rule_string.scan(/[BS]\d+/)
18
- raise ArgumentError.new("Invalid rule string #{rule_string}") if rules.length != 2
19
- birth_string = rules.select {|s| s.start_with?('B')}.first
20
- survive_string = rules.select {|s| s.start_with?('S')}.first
21
- (birth, survive) = [birth_string, survive_string].map { |s| s[1..-1].split('').map(&:to_i) }
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
@@ -1,3 +1,3 @@
1
1
  module CellularAutomata
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -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.2
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-05-24 00:00:00.000000000 Z
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: releasy
34
+ name: rmagick
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '1'
39
+ version: '2'
34
40
  - - ">="
35
41
  - !ruby/object:Gem::Version
36
- version: '1.8'
37
- type: :development
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: '1'
49
+ version: '2'
44
50
  - - ">="
45
51
  - !ruby/object:Gem::Version
46
- version: '1.8'
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.2.2
201
+ rubygems_version: 2.4.7
168
202
  signing_key:
169
203
  specification_version: 4
170
204
  summary: A simulation of cellular automata