nlife 0.0.0 → 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.
- 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: []
|