rlife 0.0.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/README +5 -0
- data/Rakefile +12 -0
- data/lib/cell.rb +44 -0
- data/lib/cellgrid.rb +66 -0
- data/lib/conway_fx_gui.rb +89 -0
- data/lib/fx_grid_canvas.rb +89 -0
- data/test/test_cell.rb +83 -0
- data/test/test_cellgrid.rb +110 -0
- metadata +61 -0
data/README
ADDED
data/Rakefile
ADDED
data/lib/cell.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
class Cell
|
2
|
+
attr_accessor :cell_state
|
3
|
+
attr_writer :queued_state
|
4
|
+
attr_reader :neighbors
|
5
|
+
protected :neighbors
|
6
|
+
|
7
|
+
# creates a new Cell with a state of "dead"
|
8
|
+
def initialize
|
9
|
+
@neighbors = []
|
10
|
+
@cell_state = :dead
|
11
|
+
@queued_state = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
# adds a neighbor to this cell. this
|
15
|
+
# method takes care of hooking up the bi-directional
|
16
|
+
# relationship so the 2 cells do not need to be added
|
17
|
+
# to each other as neighbors, only 1 of them needs
|
18
|
+
# to be notified of the relationship
|
19
|
+
def add_neighbor(cell)
|
20
|
+
unless @neighbors.include? cell
|
21
|
+
@neighbors << cell
|
22
|
+
cell.neighbors << self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# return the number of neighbors that this cell has
|
27
|
+
def number_of_neighbors
|
28
|
+
@neighbors.size
|
29
|
+
end
|
30
|
+
|
31
|
+
# returns the number of live neighbors this cell has
|
32
|
+
def number_of_live_neighbors
|
33
|
+
live_neighbors = @neighbors.find_all {|cell| cell.cell_state == :live}
|
34
|
+
live_neighbors.size
|
35
|
+
end
|
36
|
+
|
37
|
+
# Transitions this cell to its next state of evolution
|
38
|
+
def transition_state
|
39
|
+
if @queued_state != nil
|
40
|
+
@cell_state = @queued_state
|
41
|
+
@queued_state = nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/cellgrid.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'cell'
|
2
|
+
|
3
|
+
class CellGrid
|
4
|
+
|
5
|
+
def initialize (rows, columns)
|
6
|
+
@cells = Array.new rows
|
7
|
+
for row in 0...rows
|
8
|
+
@cells[row] = Array.new columns
|
9
|
+
for column in 0...columns
|
10
|
+
cell = Cell.new
|
11
|
+
@cells[row][column] = cell
|
12
|
+
if row > 0
|
13
|
+
cell.add_neighbor @cells[row-1][column]
|
14
|
+
cell.add_neighbor @cells[row-1][column+1] if column <= columns - 2
|
15
|
+
end
|
16
|
+
if column > 0
|
17
|
+
cell.add_neighbor @cells[row][column-1]
|
18
|
+
cell.add_neighbor @cells[row-1][column-1] if row > 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def cell_at (row, column)
|
25
|
+
@cells[row][column]
|
26
|
+
end
|
27
|
+
|
28
|
+
def row_count
|
29
|
+
@cells.size
|
30
|
+
end
|
31
|
+
|
32
|
+
def column_count
|
33
|
+
@cells[0].size
|
34
|
+
end
|
35
|
+
|
36
|
+
def evolve
|
37
|
+
each_cell do |cell|
|
38
|
+
# kill the lonely
|
39
|
+
cell.queued_state = :dead if cell.cell_state == :live && cell.number_of_live_neighbors < 2
|
40
|
+
|
41
|
+
# kill the overcrowded
|
42
|
+
cell.queued_state = :dead if cell.cell_state == :live && cell.number_of_live_neighbors > 3
|
43
|
+
|
44
|
+
# give birth
|
45
|
+
cell.queued_state = :live if cell.cell_state == :dead && cell.number_of_live_neighbors == 3
|
46
|
+
end
|
47
|
+
each_cell do |cell|
|
48
|
+
cell.transition_state
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def kill_all
|
53
|
+
each_cell do |cell|
|
54
|
+
cell.cell_state = :dead
|
55
|
+
cell.queued_state = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def each_cell
|
60
|
+
@cells.each do |row|
|
61
|
+
row.each do |cell|
|
62
|
+
yield cell
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'fox14'
|
2
|
+
require 'fx_grid_canvas'
|
3
|
+
require 'cellgrid'
|
4
|
+
include Fox
|
5
|
+
|
6
|
+
class ConwayWindow < FXMainWindow
|
7
|
+
WIDTH = 769
|
8
|
+
HEIGHT = 430
|
9
|
+
GRIDSIZE = 25
|
10
|
+
def initialize(app)
|
11
|
+
super(app, "RLife - Conways Game Of Life", nil, nil, DECOR_TITLE | DECOR_BORDER | DECOR_CLOSE |LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, WIDTH, HEIGHT)
|
12
|
+
FXToolTip.new(app)
|
13
|
+
FXStatusBar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
|
14
|
+
@cell_grid = CellGrid.new(16, 16)
|
15
|
+
|
16
|
+
rightFrame = FXVerticalFrame.new(self,LAYOUT_SIDE_TOP|LAYOUT_SIDE_RIGHT|LAYOUT_FILL_Y)
|
17
|
+
desc = <<EOS
|
18
|
+
Conway's Game Of Life is a cellular automaton originally conceived by
|
19
|
+
John Conway in the early 1970's.
|
20
|
+
|
21
|
+
Use the mouse to interactively define a starting grid by clicking on
|
22
|
+
cells in the grid to bring them to life. Clicking on a cell toggles its
|
23
|
+
live state. Click and drag to bring a bunch of cells to life. Live
|
24
|
+
cells are represented with green circles.
|
25
|
+
|
26
|
+
The rules of evolution are as follows:
|
27
|
+
|
28
|
+
- If a live cell has more than 3 live neighbors, it dies from overcrowding
|
29
|
+
- If a live cell has fewer than 2 live neighbors, it dies from loneliness
|
30
|
+
- If a dead cell has exactly 3 live neighbors, it comes to life
|
31
|
+
|
32
|
+
Click the \"Evolve\" button to iterate through generations one at a time.
|
33
|
+
Click the "Clear" button to clear the grid.
|
34
|
+
EOS
|
35
|
+
FXLabel.new(rightFrame, desc, nil, JUSTIFY_LEFT)
|
36
|
+
buttonFrame = FXHorizontalFrame.new(rightFrame,
|
37
|
+
LAYOUT_SIDE_TOP|LAYOUT_SIDE_RIGHT|LAYOUT_FILL_Y)
|
38
|
+
nextGenerationButton = FXButton.new(buttonFrame,
|
39
|
+
"&Evolve\tEvolve The System\tEvolve The System",
|
40
|
+
nil, nil, 0,FRAME_RAISED|FRAME_THICK|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0, 0,
|
41
|
+
70, 30)
|
42
|
+
clearButton = FXButton.new(buttonFrame,
|
43
|
+
"&Clear\tClear all live cells\tClear all live cells",
|
44
|
+
nil, nil, 0,FRAME_RAISED|FRAME_THICK|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0, 0,
|
45
|
+
70, 30)
|
46
|
+
quitButton = FXButton.new(buttonFrame,
|
47
|
+
"&Quit\tExit the Program\tExit the Program",
|
48
|
+
nil, nil, 0,FRAME_RAISED|FRAME_THICK|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0, 0,
|
49
|
+
70, 30)
|
50
|
+
canvasFrame = FXVerticalFrame.new(self,
|
51
|
+
FRAME_RIDGE|LAYOUT_FILL_X|LAYOUT_FILL_Y|
|
52
|
+
LAYOUT_TOP|LAYOUT_LEFT,
|
53
|
+
0, 0, 0, 0, 0,0,0,0)
|
54
|
+
@canvas = GridCanvas.new(canvasFrame, @cell_grid)
|
55
|
+
|
56
|
+
quitButton.connect(SEL_COMMAND) {
|
57
|
+
getApp().exit(0)
|
58
|
+
}
|
59
|
+
|
60
|
+
nextGenerationButton.connect(SEL_COMMAND) {
|
61
|
+
@cell_grid.evolve
|
62
|
+
@canvas.draw_grid
|
63
|
+
}
|
64
|
+
|
65
|
+
clearButton.connect(SEL_COMMAND) {
|
66
|
+
@cell_grid.kill_all
|
67
|
+
@canvas.draw_grid
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def create
|
72
|
+
super
|
73
|
+
show(PLACEMENT_SCREEN)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if __FILE__ == $0
|
78
|
+
# Construct an application
|
79
|
+
application = FXApp.new("RLife", "rubygroup")
|
80
|
+
|
81
|
+
# Construct the main window
|
82
|
+
ConwayWindow.new(application)
|
83
|
+
|
84
|
+
# Create the application
|
85
|
+
application.create
|
86
|
+
|
87
|
+
# Run it
|
88
|
+
application.run
|
89
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'fox14'
|
2
|
+
require 'fox14/colors'
|
3
|
+
require 'cellgrid'
|
4
|
+
|
5
|
+
include Fox
|
6
|
+
|
7
|
+
class GridCanvas < FXCanvas
|
8
|
+
GRIDSIZE = 25
|
9
|
+
def initialize(frame, cell_grid)
|
10
|
+
super(frame, nil, 0, FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
|
11
|
+
@cell_grid = cell_grid
|
12
|
+
@width = @cell_grid.column_count * GRIDSIZE
|
13
|
+
@height = @cell_grid.row_count * GRIDSIZE
|
14
|
+
@grid_background = FXColor::DarkGray
|
15
|
+
@grid_foreground = FXColor::LightGray
|
16
|
+
@live_cell_color = FXColor::SpringGreen
|
17
|
+
@dragging = false
|
18
|
+
connect(SEL_PAINT) do |sender, sel, event|
|
19
|
+
draw_grid
|
20
|
+
end
|
21
|
+
|
22
|
+
# the dragging stuff here is almost certainly not the
|
23
|
+
# "correct" way to git-r-dun... pending enlightenment
|
24
|
+
connect(SEL_LEFTBUTTONPRESS) do |sender, sel, event|
|
25
|
+
toggle_cell_at_location(event.click_x, event.click_y)
|
26
|
+
@dragging = true
|
27
|
+
end
|
28
|
+
connect(SEL_LEFTBUTTONRELEASE) do |sender, sel, event|
|
29
|
+
@dragging = false
|
30
|
+
end
|
31
|
+
connect(SEL_MOTION) do |sender, sel, event|
|
32
|
+
handle_drag(event.win_x, event.win_y) if @dragging
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def draw_grid
|
37
|
+
FXDCWindow.new(self) do |dc|
|
38
|
+
self.backColor = @grid_background
|
39
|
+
dc.foreground = self.backColor
|
40
|
+
dc.fillRectangle(0, 0, width, height)
|
41
|
+
dc.foreground = @grid_foreground
|
42
|
+
0.step(@width, GRIDSIZE) do |column|
|
43
|
+
dc.drawLine(column, 0, column, @height)
|
44
|
+
end
|
45
|
+
0.step(@height, GRIDSIZE) do |row|
|
46
|
+
dc.drawLine(0, row, @width, row)
|
47
|
+
end
|
48
|
+
dc.foreground = @live_cell_color
|
49
|
+
for row in 0...@cell_grid.row_count
|
50
|
+
for column in 0...@cell_grid.column_count
|
51
|
+
cell = @cell_grid.cell_at(row, column)
|
52
|
+
if(cell.cell_state == :live)
|
53
|
+
x = (column * GRIDSIZE) + (GRIDSIZE / 2)
|
54
|
+
y = (row * GRIDSIZE) + (GRIDSIZE / 2)
|
55
|
+
dc.fillCircle(x, y, GRIDSIZE / 3)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_drag(x, y)
|
63
|
+
cell = cell_at_location(x, y)
|
64
|
+
if cell && cell.cell_state == :dead
|
65
|
+
cell.cell_state = :live
|
66
|
+
draw_grid
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def toggle_cell_at_location(x, y)
|
71
|
+
cell = cell_at_location(x, y)
|
72
|
+
if cell
|
73
|
+
if cell.cell_state == :dead
|
74
|
+
cell.cell_state = :live
|
75
|
+
else
|
76
|
+
cell.cell_state = :dead
|
77
|
+
end
|
78
|
+
draw_grid
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def cell_at_location(x, y)
|
83
|
+
cell = nil
|
84
|
+
column = x / GRIDSIZE
|
85
|
+
row = y / GRIDSIZE
|
86
|
+
cell = @cell_grid.cell_at(row, column) if column < @cell_grid.column_count && row < @cell_grid.row_count
|
87
|
+
cell
|
88
|
+
end
|
89
|
+
end
|
data/test/test_cell.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'cell'
|
3
|
+
|
4
|
+
class CellTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_initial_state
|
7
|
+
c = Cell.new
|
8
|
+
assert_equal :dead, c.cell_state
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_add_neighbor
|
12
|
+
c1 = Cell.new
|
13
|
+
c2 = Cell.new
|
14
|
+
assert_equal 0, c1.number_of_neighbors
|
15
|
+
assert_equal 0, c2.number_of_neighbors
|
16
|
+
|
17
|
+
c1.add_neighbor c2
|
18
|
+
|
19
|
+
assert_equal 1, c1.number_of_neighbors
|
20
|
+
assert_equal 1, c2.number_of_neighbors
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_add_neighbor_multiple_times
|
24
|
+
c1 = Cell.new
|
25
|
+
c2 = Cell.new
|
26
|
+
assert_equal 0, c1.number_of_neighbors
|
27
|
+
assert_equal 0, c2.number_of_neighbors
|
28
|
+
|
29
|
+
c1.add_neighbor c2
|
30
|
+
c1.add_neighbor c2
|
31
|
+
|
32
|
+
assert_equal 1, c1.number_of_neighbors
|
33
|
+
assert_equal 1, c2.number_of_neighbors
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_number_of_live_neighbors
|
37
|
+
c1 = Cell.new
|
38
|
+
c2 = Cell.new
|
39
|
+
c3 = Cell.new
|
40
|
+
|
41
|
+
c1.add_neighbor c2
|
42
|
+
|
43
|
+
assert_equal 0, c1.number_of_live_neighbors
|
44
|
+
|
45
|
+
c2.cell_state = :live
|
46
|
+
|
47
|
+
assert_equal 1, c1.number_of_live_neighbors
|
48
|
+
|
49
|
+
c3.cell_state = :live
|
50
|
+
c1.add_neighbor c3
|
51
|
+
assert_equal 2, c1.number_of_live_neighbors
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_state_queuing
|
55
|
+
c1 = Cell.new
|
56
|
+
assert_equal :dead, c1.cell_state
|
57
|
+
|
58
|
+
c1.cell_state = :live
|
59
|
+
assert_equal :live, c1.cell_state
|
60
|
+
|
61
|
+
c1.queued_state = :dead
|
62
|
+
assert_equal :live, c1.cell_state
|
63
|
+
|
64
|
+
c1.transition_state
|
65
|
+
assert_equal :dead, c1.cell_state
|
66
|
+
|
67
|
+
c1.queued_state = :live
|
68
|
+
assert_equal :dead, c1.cell_state
|
69
|
+
|
70
|
+
c1.transition_state
|
71
|
+
assert_equal :live, c1.cell_state
|
72
|
+
|
73
|
+
c1.transition_state
|
74
|
+
assert_equal :live, c1.cell_state
|
75
|
+
|
76
|
+
c1.cell_state = :dead
|
77
|
+
assert_equal :dead, c1.cell_state
|
78
|
+
|
79
|
+
c1.transition_state
|
80
|
+
assert_equal :dead, c1.cell_state
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'cell'
|
2
|
+
require 'cellgrid'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class CellGridTest < Test::Unit::TestCase
|
6
|
+
ROWS = 10
|
7
|
+
COLUMNS = 5
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@cell_grid = CellGrid.new ROWS, COLUMNS
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_get_cell_at
|
14
|
+
cell = @cell_grid.cell_at(2, 2)
|
15
|
+
assert_not_nil cell
|
16
|
+
assert_equal :dead, cell.cell_state
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_column_count
|
20
|
+
assert_equal COLUMNS, @cell_grid.column_count
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_row_count
|
24
|
+
assert_equal ROWS, @cell_grid.row_count
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_number_of_neighbors
|
28
|
+
cell = @cell_grid.cell_at(0, 0)
|
29
|
+
|
30
|
+
# corner cells should all have 3 neighbors
|
31
|
+
assert_equal 3, cell.number_of_neighbors
|
32
|
+
cell = @cell_grid.cell_at(0, COLUMNS - 1)
|
33
|
+
assert_equal 3, cell.number_of_neighbors
|
34
|
+
cell = @cell_grid.cell_at(ROWS - 1, COLUMNS - 1)
|
35
|
+
assert_equal 3, cell.number_of_neighbors
|
36
|
+
cell = @cell_grid.cell_at(ROWS - 1, 0)
|
37
|
+
assert_equal 3, cell.number_of_neighbors
|
38
|
+
|
39
|
+
# cells in the first and last row (except corners) should all have 5 neighbors
|
40
|
+
for column in 1...COLUMNS-1
|
41
|
+
cell = @cell_grid.cell_at(0, column)
|
42
|
+
assert_equal 5, cell.number_of_neighbors
|
43
|
+
cell = @cell_grid.cell_at(ROWS - 1, column)
|
44
|
+
assert_equal 5, cell.number_of_neighbors
|
45
|
+
end
|
46
|
+
|
47
|
+
# cells in the first and last column (except corners) should all ahve 5 neighbors
|
48
|
+
for row in 1...ROWS-1
|
49
|
+
cell = @cell_grid.cell_at(row, 0)
|
50
|
+
assert_equal 5, cell.number_of_neighbors
|
51
|
+
cell = @cell_grid.cell_at(row, COLUMNS-1)
|
52
|
+
assert_equal 5, cell.number_of_neighbors
|
53
|
+
end
|
54
|
+
|
55
|
+
# cells not along the edges should each have 8 neighbors
|
56
|
+
for row in 1...ROWS-1
|
57
|
+
for column in 1...COLUMNS-1
|
58
|
+
cell = @cell_grid.cell_at(row, column)
|
59
|
+
assert_equal 8, cell.number_of_neighbors
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_lonely_cell
|
65
|
+
cell = @cell_grid.cell_at(3, 3)
|
66
|
+
assert_equal :dead, cell.cell_state
|
67
|
+
cell.cell_state = :live
|
68
|
+
@cell_grid.evolve
|
69
|
+
assert_equal :dead, cell.cell_state
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_overcrowded_cell
|
73
|
+
c1 = @cell_grid.cell_at(0, 0)
|
74
|
+
c1.cell_state = :live
|
75
|
+
c2 = @cell_grid.cell_at(1, 0)
|
76
|
+
c2.cell_state = :live
|
77
|
+
c3 = @cell_grid.cell_at(2, 0)
|
78
|
+
c3.cell_state = :live
|
79
|
+
c4 = @cell_grid.cell_at(0, 1)
|
80
|
+
c4.cell_state = :live
|
81
|
+
crowded_cell = @cell_grid.cell_at(1, 1)
|
82
|
+
crowded_cell.cell_state = :live
|
83
|
+
|
84
|
+
@cell_grid.evolve
|
85
|
+
|
86
|
+
assert_equal :dead, crowded_cell.cell_state
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_new_birth
|
90
|
+
c1 = @cell_grid.cell_at(0, 0)
|
91
|
+
c1.cell_state = :live
|
92
|
+
c2 = @cell_grid.cell_at(1, 0)
|
93
|
+
c2.cell_state = :live
|
94
|
+
c3 = @cell_grid.cell_at(2, 0)
|
95
|
+
c3.cell_state = :live
|
96
|
+
|
97
|
+
candidate_cell = @cell_grid.cell_at(1, 1)
|
98
|
+
|
99
|
+
assert_equal :dead, candidate_cell.cell_state
|
100
|
+
@cell_grid.evolve
|
101
|
+
assert_equal :live, candidate_cell.cell_state
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_kill_all
|
105
|
+
c1 = @cell_grid.cell_at(3, 3)
|
106
|
+
c1.cell_state = :live
|
107
|
+
@cell_grid.kill_all
|
108
|
+
assert_equal :dead, c1.cell_state
|
109
|
+
end
|
110
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: rlife
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2006-06-14 00:00:00 -05:00
|
8
|
+
summary: A Ruby implementation of Conway's Game Of Life
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: brown_j@ociweb.com
|
12
|
+
homepage: http://rubyforge.org/projects/rlife
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: conway_fx_gui
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Jeff S. Brown
|
30
|
+
files:
|
31
|
+
- lib/cell.rb
|
32
|
+
- lib/cellgrid.rb
|
33
|
+
- lib/conway_fx_gui.rb
|
34
|
+
- lib/fx_grid_canvas.rb
|
35
|
+
- Rakefile
|
36
|
+
- README
|
37
|
+
- test/test_cell.rb
|
38
|
+
- test/test_cellgrid.rb
|
39
|
+
test_files:
|
40
|
+
- test/test_cell.rb
|
41
|
+
- test/test_cellgrid.rb
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
executables: []
|
47
|
+
|
48
|
+
extensions: []
|
49
|
+
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
dependencies:
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: fxruby
|
55
|
+
version_requirement:
|
56
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.4.4
|
61
|
+
version:
|