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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: adee4e0a608c42f3780cf331194e63b8e788e604
4
- data.tar.gz: a59630d9e1f36ae189afc28db948423a7ce29f24
3
+ metadata.gz: bb3319cf910fe04786b885de262b96e56f69e56d
4
+ data.tar.gz: e4cc2675fc16bcfb6e5b33d7cd48f6acc33f99ac
5
5
  SHA512:
6
- metadata.gz: 093eabd1b18af761c77d3e6ad046f344aa840ffc656203ea077c8df5a98f76dc505cc84d4a13858865ba68ef92e79249fa52e3dd95113d391a0564c34e264e03
7
- data.tar.gz: 140fbdc9ccea78efd8350979dec45853b5c05686ea75808ef3c4085a274f521d46664434f086a98feb0427020269d1f24a16b2ec5e1c23ec22776904248de042
6
+ metadata.gz: 49f7c216349321a856e2f9900bc00d9959ea5458d22cd2ffab0e8bf9ec3c69f7eecfa071268bc274549e93e7a18bd697085d0e03c1f0cabc2e2de0acb64f37d5
7
+ data.tar.gz: 40705b57e94c5a6b14c1ba640b60a057d7d08ac995eddf97a2e16c32d93ddfa33861da2d7c03e18cf2fb9ccba0227178964dc84b9bda84e194a010ac18e74806
@@ -0,0 +1,17 @@
1
+ GAME OF LIFE WITH CURSES VIEWER
2
+ ===============================
3
+
4
+ ### Controls
5
+ - p: pause
6
+ - s: seed
7
+ - q: quit
8
+
9
+ ### Documentation
10
+ To be added
11
+
12
+ ### Tests
13
+ To be added
14
+
15
+ ### How to use
16
+ $ gem install nlife
17
+ $ nlife
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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/nlife"
4
+
5
+ NLife::UI.new.start
@@ -1,5 +1 @@
1
- class NLife
2
- def self.hi
3
- puts "Hello, world!"
4
- end
5
- end
1
+ require_relative "nlife/ui"
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module NLife
2
+ VERSION = '0.0.1'
3
+ end
@@ -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.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-13 00:00:00.000000000 Z
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
- - MIT
93
+ - LGPL-3.0
23
94
  metadata: {}
24
95
  post_install_message:
25
96
  rdoc_options: []