nlife 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -0
- data/TODO.md +31 -0
- data/bin/nlife +5 -0
- data/lib/nlife.rb +1 -5
- data/lib/nlife/game.rb +74 -0
- data/lib/nlife/helper.rb +34 -0
- data/lib/nlife/ui.rb +72 -0
- data/lib/nlife/version.rb +3 -0
- data/nlife.gemspec +20 -0
- metadata +76 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb3319cf910fe04786b885de262b96e56f69e56d
|
4
|
+
data.tar.gz: e4cc2675fc16bcfb6e5b33d7cd48f6acc33f99ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49f7c216349321a856e2f9900bc00d9959ea5458d22cd2ffab0e8bf9ec3c69f7eecfa071268bc274549e93e7a18bd697085d0e03c1f0cabc2e2de0acb64f37d5
|
7
|
+
data.tar.gz: 40705b57e94c5a6b14c1ba640b60a057d7d08ac995eddf97a2e16c32d93ddfa33861da2d7c03e18cf2fb9ccba0227178964dc84b9bda84e194a010ac18e74806
|
data/README.md
ADDED
data/TODO.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
TODO
|
2
|
+
====
|
3
|
+
|
4
|
+
### Tests
|
5
|
+
- add rspec tests
|
6
|
+
|
7
|
+
### Game features
|
8
|
+
- resizing grid
|
9
|
+
- load/save file
|
10
|
+
- set cell state
|
11
|
+
- yank/paste/clear region
|
12
|
+
|
13
|
+
### Render features
|
14
|
+
- make render a separate class
|
15
|
+
- options for live/dead cell characters
|
16
|
+
- zoom/viewport settings
|
17
|
+
- show density
|
18
|
+
|
19
|
+
### Bin features
|
20
|
+
- use Thor in bin/nlife
|
21
|
+
- manual setting
|
22
|
+
- grid size
|
23
|
+
- delay
|
24
|
+
- input file
|
25
|
+
|
26
|
+
### UI features
|
27
|
+
- add more controls
|
28
|
+
- speed control
|
29
|
+
- scroll
|
30
|
+
- mouse support
|
31
|
+
- draw/clear/yank/paste tool
|
data/bin/nlife
ADDED
data/lib/nlife.rb
CHANGED
data/lib/nlife/game.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require "narray"
|
2
|
+
require "numru/fftw3"
|
3
|
+
include NumRu
|
4
|
+
|
5
|
+
require_relative "./helper.rb"
|
6
|
+
|
7
|
+
module NLife
|
8
|
+
class Game
|
9
|
+
attr_reader :state
|
10
|
+
attr_accessor :density
|
11
|
+
|
12
|
+
def initialize(rows, cols, surround = nil, rule = nil)
|
13
|
+
@state = NArray.int(cols, rows)
|
14
|
+
@density = NArray.int(cols, rows)
|
15
|
+
surround ||= default_surround(rows, cols)
|
16
|
+
@t_surround = FFTW3.fft(surround.to_f, -1) / surround.size
|
17
|
+
@rule = rule || default_rule
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_surround(rows, cols)
|
21
|
+
return Helper.surround_from_block(rows, cols) do |row, col|
|
22
|
+
[row.abs, col.abs].max == 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_rule
|
27
|
+
return Helper.rule_from_golly("B3/S23")
|
28
|
+
end
|
29
|
+
|
30
|
+
def seed
|
31
|
+
@state.shape[1].times do |row|
|
32
|
+
@state.shape[0].times do |col|
|
33
|
+
@state[col, row] = rand.round
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def step
|
39
|
+
calc_density
|
40
|
+
calc_next_state
|
41
|
+
end
|
42
|
+
|
43
|
+
def calc_density
|
44
|
+
t_state = FFTW3.fft(@state, -1)
|
45
|
+
t_density = t_state * @t_surround
|
46
|
+
@density = FFTW3.fft(t_density, 1).real.round
|
47
|
+
end
|
48
|
+
|
49
|
+
def calc_next_state
|
50
|
+
@state.shape[1].times do |row|
|
51
|
+
@state.shape[0].times do |col|
|
52
|
+
@state[col, row] = @rule.call(@state[col, row], @density[col, row])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# use for debug only
|
58
|
+
def print
|
59
|
+
puts "#" * (@state.shape[0] + 2)
|
60
|
+
@state.shape[1].times do |i|
|
61
|
+
puts "#" + @state[true, i].each.map { |e| e > 0 ? "*" : " " }.join + "#"
|
62
|
+
end
|
63
|
+
puts "#" * (@state.shape[0] + 2)
|
64
|
+
end
|
65
|
+
|
66
|
+
def rows
|
67
|
+
@state.shape[1]
|
68
|
+
end
|
69
|
+
|
70
|
+
def cols
|
71
|
+
@state.shape[0]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/nlife/helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "narray"
|
2
|
+
|
3
|
+
module NLife
|
4
|
+
module Helper
|
5
|
+
def self.surround_from_block(rows, cols)
|
6
|
+
result = NArray.int(cols, rows)
|
7
|
+
result.shape[1].times do |row|
|
8
|
+
result.shape[0].times do |col|
|
9
|
+
result[col, row] = yield((row + rows / 2) % rows - rows / 2,
|
10
|
+
(col + cols / 2) % cols - cols / 2) ? 1 : 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
16
|
+
# constructs rules from two arrays, birth/survival densities
|
17
|
+
def self.rule_from_arrays(birth, survival)
|
18
|
+
proc do |state, density|
|
19
|
+
birth[density.round] || state > 0 && survival[density.round] ? 1 : 0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# constructs rules from string, describing birth/survival densities
|
24
|
+
def self.rule_from_golly(string)
|
25
|
+
match = /^B([0-8]*)\/S([0-8]*)$/.match(string)
|
26
|
+
Raise ArgumentError "Wrong input format" unless match
|
27
|
+
birth = Array.new(9, false)
|
28
|
+
survival = Array.new(9, false)
|
29
|
+
match[1].split(//).map(&:to_i).each { |i| birth[i] = true }
|
30
|
+
match[2].split(//).map(&:to_i).each { |i| survival[i] = true }
|
31
|
+
return rule_from_arrays(birth, survival)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/nlife/ui.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'curses'
|
2
|
+
|
3
|
+
require_relative "./game.rb"
|
4
|
+
|
5
|
+
module NLife
|
6
|
+
class UI
|
7
|
+
RENDER_DEAD = " "
|
8
|
+
RENDER_LIVE = "\u2588"
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
init_settings
|
12
|
+
init_window
|
13
|
+
init_life
|
14
|
+
end
|
15
|
+
|
16
|
+
def init_window
|
17
|
+
Curses.init_screen
|
18
|
+
Curses.curs_set(0)
|
19
|
+
Curses.noecho
|
20
|
+
@window_lines = Curses.lines
|
21
|
+
@window_cols = Curses.cols
|
22
|
+
@window = Curses::Window.new(@window_lines, @window_cols, 0, 0)
|
23
|
+
@window.box("|", "-")
|
24
|
+
@window.timeout = 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def init_life
|
28
|
+
@life = NLife::Game.new(@window_lines - 2, @window_cols - 2) # padding
|
29
|
+
@life.seed
|
30
|
+
end
|
31
|
+
|
32
|
+
def init_settings
|
33
|
+
@pause = false
|
34
|
+
@delay = 0.04
|
35
|
+
end
|
36
|
+
|
37
|
+
def start
|
38
|
+
loop do
|
39
|
+
break unless dispatch_key(@window.getch)
|
40
|
+
step
|
41
|
+
render
|
42
|
+
sleep(@delay)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def dispatch_key(key)
|
47
|
+
case key
|
48
|
+
when "p" then @pause = !@pause
|
49
|
+
when "s" then @life.seed
|
50
|
+
when "q" then return false
|
51
|
+
end
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
|
55
|
+
def step
|
56
|
+
unless @pause
|
57
|
+
@life.step
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def render
|
62
|
+
@life.rows.times do |i|
|
63
|
+
string = ""
|
64
|
+
@life.cols.times do |j|
|
65
|
+
string += @life.state[j, i] > 0 ? RENDER_LIVE : RENDER_DEAD
|
66
|
+
end
|
67
|
+
@window.setpos(i + 1, 1)
|
68
|
+
@window.addstr(string)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/nlife.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative './lib/nlife/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'nlife'
|
5
|
+
s.version = NLife::VERSION
|
6
|
+
s.licenses = ['LGPL-3.0']
|
7
|
+
s.authors = ["Oleg Zubchenko"]
|
8
|
+
s.email = 'RedGreenBlueDiamond@gmail.com'
|
9
|
+
s.homepage = 'http://rubygems.org/gems/nlife'
|
10
|
+
s.summary = "Generalized Game of Life"
|
11
|
+
s.description = "Customizable Game of Life with ncurses viewer"
|
12
|
+
s.files = Dir["lib/**/*.rb"] + Dir["bin/*"] + Dir["*.md"] +
|
13
|
+
Dir["*.gemspec"]
|
14
|
+
s.executables << 'nlife'
|
15
|
+
|
16
|
+
s.add_runtime_dependency 'curses', '~> 1.0', '>= 1.0.1'
|
17
|
+
s.add_runtime_dependency 'narray', '~>0.6.1'
|
18
|
+
s.add_runtime_dependency 'numru-misc', '~>0.1.2'
|
19
|
+
s.add_runtime_dependency 'ruby-fftw3', '~>0.4.2'
|
20
|
+
end
|
metadata
CHANGED
@@ -1,25 +1,96 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nlife
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Zubchenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
12
|
-
dependencies:
|
11
|
+
date: 2015-05-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: curses
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: narray
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.6.1
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.6.1
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: numru-misc
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.1.2
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.1.2
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: ruby-fftw3
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.4.2
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.4.2
|
13
75
|
description: Customizable Game of Life with ncurses viewer
|
14
76
|
email: RedGreenBlueDiamond@gmail.com
|
15
|
-
executables:
|
77
|
+
executables:
|
78
|
+
- nlife
|
16
79
|
extensions: []
|
17
80
|
extra_rdoc_files: []
|
18
81
|
files:
|
82
|
+
- README.md
|
83
|
+
- TODO.md
|
84
|
+
- bin/nlife
|
19
85
|
- lib/nlife.rb
|
86
|
+
- lib/nlife/game.rb
|
87
|
+
- lib/nlife/helper.rb
|
88
|
+
- lib/nlife/ui.rb
|
89
|
+
- lib/nlife/version.rb
|
90
|
+
- nlife.gemspec
|
20
91
|
homepage: http://rubygems.org/gems/nlife
|
21
92
|
licenses:
|
22
|
-
-
|
93
|
+
- LGPL-3.0
|
23
94
|
metadata: {}
|
24
95
|
post_install_message:
|
25
96
|
rdoc_options: []
|