game0flife 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2bcd04f0f85d58cc1083b511f60fa6ce4cd2af6cc2ad07b42ba96b5864e75228
4
+ data.tar.gz: af2b01eca8090a28fdefed4db2401b4cc34380a9ad28588525a1316a99c3e4ee
5
+ SHA512:
6
+ metadata.gz: b24fffd43329459165b64e24721ad2a5382912a1ac35f9105a29536122e344b56ce43601812366a99b2ea6b9a09d669acf18b8c01f83da35351c7ea07d62aa1b
7
+ data.tar.gz: c6233b6c7f87d725122764dc4f3859d66070d6c6482608f3581bb7b687930b4aa68d3d7d7604de4e17b7d5b4ca4b9da566f0fd62274e16d2d32443c350572d49
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require_relative '../lib/grid.rb'
6
+ require_relative '../lib/cell.rb'
7
+ require_relative '../lib/display.rb'
8
+
9
+ # main application class
10
+ class Game0fLife
11
+ DEF_FRAMERATE = 60
12
+ DEF_PATTERN_X = 20
13
+ DEF_PATTERN_Y = 20
14
+
15
+ def initialize
16
+ @grid = Grid.new
17
+ @framerate = parse_arg('framerate') || DEF_FRAMERATE
18
+ @pattern = parse_arg('pattern')
19
+ prep_grid_for_pattern_render if @pattern
20
+ end
21
+
22
+ def prep_grid_for_pattern_render
23
+ @grid.reset
24
+ @grid.load_pattern(
25
+ @pattern.to_sym,
26
+ parse_arg('pattern_x') || DEF_PATTERN_X,
27
+ parse_arg('pattern_y') || DEF_PATTERN_Y
28
+ )
29
+ end
30
+
31
+ def help
32
+ puts <<-POSTMSG
33
+
34
+ ██████  █████  ███  ███ ███████  ██████  ███████ ██  ██ ███████ ███████ 
35
+ ██       ██   ██ ████  ████ ██      ██  ████ ██      ██  ██ ██      ██      
36
+ ██  ███ ███████ ██ ████ ██ █████  ██ ██ ██ █████  ██  ██ █████  █████ 
37
+ ██  ██ ██   ██ ██  ██  ██ ██     ████  ██ ██     ██  ██ ██     ██    
38
+  ██████  ██  ██ ██      ██ ███████  ██████  ██  ███████ ██ ██  ███████ 
39
+
40
+ Usage:
41
+ game0flife [options]
42
+
43
+ Options:
44
+ --pattern=<acorn|diehard|r_pentomino|simple_spaceship>
45
+ --framerate=60
46
+ --pattern_x=20 (60x60 Frame)
47
+ --pattern_y=20 (60x60 Frame)
48
+
49
+ POSTMSG
50
+ end
51
+
52
+ def run
53
+ return help if ARGV.include?('--help')
54
+
55
+ Display.new(@grid, @framerate.to_i).render
56
+ end
57
+
58
+ def self.run
59
+ new.run
60
+ end
61
+
62
+ private
63
+
64
+ def parse_arg(arg_type)
65
+ ARGV.map { |arg| arg.split('=') }
66
+ .find { |arg| arg[0] == "--#{arg_type}" }
67
+ .to_a[1]
68
+ end
69
+ end
70
+
71
+ Game0fLife.run
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Population
4
+ class Cell
5
+ DEAD = ' '
6
+ ALIVE = '█'
7
+ attr_reader :state, :coordinates
8
+
9
+ def initialize(state, *coordinates)
10
+ @coordinates = coordinates
11
+ @state = state
12
+ n_indices
13
+ end
14
+
15
+ def n_indices
16
+ @n_indices ||= neighbor_indices
17
+ end
18
+
19
+ def dead?
20
+ @state == DEAD
21
+ end
22
+
23
+ def alive?
24
+ @state == ALIVE
25
+ end
26
+
27
+ def next_gen_fate(live_ncells)
28
+ if @state == ALIVE
29
+ (2..3).cover?(live_ncells) ? ALIVE : DEAD
30
+ elsif @state == DEAD
31
+ live_ncells == 3 ? ALIVE : DEAD
32
+ end
33
+ end
34
+ end
35
+
36
+ def neighbor_indices
37
+ y_neighbors = [-1, 0, 1].product([@coordinates[1]]).map(&:sum)
38
+ x_neighbors = [-1, 0, 1].product([@coordinates[0]]).map(&:sum)
39
+ neighbors = x_neighbors.product(y_neighbors)
40
+ neighbors -= [@coordinates]
41
+ neighbors.map do |n_coords|
42
+ [n_coords[0] % Grid::ROWS, n_coords[1] % Grid::COLS]
43
+ end
44
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sdl2'
4
+ require_relative 'grid.rb'
5
+ require_relative 'cell.rb'
6
+
7
+ # Graphics Display
8
+ class Display
9
+ BLACK = '000'
10
+ WHITE = 'FFF'
11
+
12
+ DSTD_HEIGHT = 600
13
+ DSTD_WIDTH = 600
14
+
15
+ attr_accessor :renderer, :window, :event_function, :framerate
16
+
17
+ def initialize(grid, framerate=60)
18
+ SDL2.init(SDL2::INIT_VIDEO | SDL2::INIT_TIMER | SDL2::INIT_EVENTS)
19
+ @window = create_window
20
+ @renderer = window.create_renderer(-1, 0)
21
+ @framerate = framerate
22
+
23
+ @grid = grid
24
+ @grid_height = Grid::ROWS
25
+ @grid_width = Grid::COLS
26
+
27
+ @cell_width = DSTD_WIDTH / Grid::COLS
28
+ @cell_height = DSTD_HEIGHT / Grid::ROWS
29
+ end
30
+
31
+ def render
32
+ loop do
33
+ event_handler
34
+
35
+ clear_screen
36
+ plot_grid
37
+ update_grid
38
+
39
+ @renderer.present
40
+ sleep 1.0 / @framerate
41
+ end
42
+ end
43
+
44
+ def event_handler
45
+ while ev = SDL2::Event.poll
46
+ if SDL2::Event::KeyDown === ev && ev.scancode == SDL2::Key::Scan::ESCAPE
47
+ exit
48
+ end
49
+ end
50
+ end
51
+
52
+ def plot_grid
53
+ @grid.map do |row|
54
+ row.map do |cell|
55
+ plot_cell(cell)
56
+ end
57
+ end
58
+ end
59
+
60
+ def update_grid
61
+ @grid.inc_gen
62
+ end
63
+
64
+ def plot_cell(cell)
65
+ @renderer.draw_color = decode_color(cell.state == Cell::ALIVE ? WHITE : BLACK)
66
+ @renderer.fill_rect(
67
+ SDL2::Rect.new(
68
+ cell.coordinates[0] * @cell_height,
69
+ cell.coordinates[1] * @cell_width,
70
+ @cell_height, @cell_width
71
+ )
72
+ )
73
+ end
74
+
75
+ def self.render_grid(grid)
76
+ new(grid).render
77
+ end
78
+
79
+ private
80
+
81
+ def clear_screen
82
+ @renderer.draw_color = decode_color(BLACK)
83
+ @renderer.clear
84
+ end
85
+
86
+ def decode_color(hex_string)
87
+ hex_string.chars.map do |color_code|
88
+ (color_code.to_i(16) / 15) * 255
89
+ end
90
+ end
91
+
92
+ def create_window
93
+ SDL2::Window.create(
94
+ "Conway's Game of Life",
95
+ SDL2::Window::POS_CENTERED,
96
+ SDL2::Window::POS_CENTERED,
97
+ DSTD_WIDTH, DSTD_HEIGHT,
98
+ 0
99
+ )
100
+ end
101
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'cell.rb'
4
+ require_relative 'display.rb'
5
+ require_relative 'seed.rb'
6
+
7
+ # Universe
8
+ class Grid
9
+ attr_reader :grid_struct
10
+ ROWS = 60
11
+ COLS = 60
12
+ DEAD = ' '
13
+ ALIVE = '█'
14
+ PBACK_SPEED = 0.000
15
+
16
+ def initialize
17
+ @grid_struct = create_grid_struct(true)
18
+ end
19
+
20
+ def load_pattern(pattern, x, y)
21
+ @grid_struct = Seed.render_to_grid(@grid_struct, pattern, x, y)
22
+ end
23
+
24
+ def reset
25
+ @grid_struct = create_grid_struct(false)
26
+ end
27
+
28
+ def create_grid_struct(randomize = false)
29
+ ROWS.times.map do |ri|
30
+ COLS.times.map do |ci|
31
+ Cell.new((randomize ? ([ALIVE] + ([DEAD] * 2)).sample : DEAD), ri, ci)
32
+ end
33
+ end
34
+ end
35
+
36
+ def map(&block)
37
+ @grid_struct.map(&block)
38
+ end
39
+
40
+ def inc_gen
41
+ @grid_struct = next_generation_grid_struct
42
+ end
43
+
44
+ def neighbor_cells(*coords)
45
+ current_cell = @grid_struct.dig(*coords)
46
+ current_cell.n_indices.map do |neighbor_cell_coords|
47
+ @grid_struct.dig(*neighbor_cell_coords)
48
+ end
49
+ end
50
+
51
+ def grid_print
52
+ print(@grid_struct.map do |row|
53
+ row.map(&:state).join
54
+ end.join("\n"))
55
+ puts
56
+ end
57
+
58
+ def next_generation_grid_struct
59
+ next_gen_grid = create_grid_struct
60
+ @grid_struct.map.with_index do |row, ri|
61
+ row.map.with_index do |cell, ci|
62
+ cn_cells = neighbor_cells(ri, ci)
63
+ next_gen_grid[ri][ci] = Cell.new(
64
+ cell.next_gen_fate(cn_cells.count(&:alive?)), ri, ci
65
+ )
66
+ end
67
+ end
68
+ next_gen_grid
69
+ end
70
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'grid.rb'
2
+ require_relative 'cell.rb'
3
+
4
+ class Seed
5
+ def self.render_to_grid(grid, pattern_name, x, y)
6
+ require_relative("./seeds/#{pattern_name}.rb")
7
+ pattern = eval("#{pattern_name.to_s.split('_').map(&:capitalize).join}::PATTERN")
8
+ pattern.map.with_index do |pattern_row, pri|
9
+ pattern_row.map.with_index do |pattern_col, pci|
10
+ grid[y+pci][x+pri] = Cell.new(pattern_col, x+pri, y+pci)
11
+ end
12
+ end
13
+ return grid
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../cell.rb'
2
+
3
+ class Acorn
4
+ PATTERN = [
5
+ [Cell::DEAD, Cell::ALIVE, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD],
6
+ [Cell::ALIVE, Cell::ALIVE, Cell::DEAD, Cell::DEAD, Cell::ALIVE, Cell::ALIVE, Cell::ALIVE, Cell::ALIVE],
7
+ [Cell::ALIVE, Cell::ALIVE, Cell::DEAD, Cell::DEAD, Cell::ALIVE, Cell::ALIVE, Cell::ALIVE, Cell::ALIVE]
8
+ ]
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../cell.rb'
2
+
3
+ class Diehard
4
+ PATTERN = [
5
+ [Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::ALIVE, Cell::DEAD],
6
+ [Cell::ALIVE, Cell::ALIVE, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::DEAD],
7
+ [Cell::DEAD, Cell::ALIVE, Cell::DEAD, Cell::DEAD, Cell::DEAD, Cell::ALIVE, Cell::ALIVE, Cell::ALIVE],
8
+ ]
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../cell.rb'
2
+
3
+ class RPentomino
4
+ PATTERN = [
5
+ [Cell::DEAD, Cell::ALIVE, Cell::ALIVE],
6
+ [Cell::ALIVE, Cell::ALIVE, Cell::DEAD],
7
+ [Cell::DEAD, Cell::ALIVE, Cell::DEAD]
8
+ ]
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../cell.rb'
2
+
3
+ class SimpleSpaceship
4
+ PATTERN = [
5
+ [Cell::DEAD, Cell::ALIVE, Cell::DEAD],
6
+ [Cell::DEAD, Cell::DEAD, Cell::ALIVE],
7
+ [Cell::ALIVE, Cell::ALIVE, Cell::ALIVE]
8
+ ].freeze
9
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: game0flife
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sreedev Kodichath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-sdl2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.3.5
27
+ description: Conway's Game of Life Implemented in Ruby & Rendered using SDL2
28
+ email: sreedevpadmakumar@gmail.com
29
+ executables:
30
+ - game0flife
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/game0flife
35
+ - lib/cell.rb
36
+ - lib/display.rb
37
+ - lib/grid.rb
38
+ - lib/seed.rb
39
+ - lib/seeds/acorn.rb
40
+ - lib/seeds/diehard.rb
41
+ - lib/seeds/r_pentomino.rb
42
+ - lib/seeds/simple_spaceship.rb
43
+ homepage: https://sree.dev/game0flife
44
+ licenses:
45
+ - MIT
46
+ metadata:
47
+ source_code_uri: https://github.com/sreedevk/game0flife
48
+ post_install_message: "\n ██████  █████  ███  ███ ███████  ██████  ███████ ██ 
49
+ \ ██ ███████ ███████ \n ██       ██   ██ ████  ████ ██      ██  ████ ██      ██ 
50
+ \ ██ ██      ██      \n ██  ███ ███████ ██ ████ ██ █████  ██ ██ ██ █████ 
51
+ \ ██  ██ █████  █████  \n ██  ██ ██   ██ ██  ██  ██ ██     ████  ██ ██    
52
+ \ ██  ██ ██     ██     \n  ██████  ██  ██ ██      ██ ███████  ██████  ██ 
53
+ \ ███████ ██ ██  ███████ \n\n Usage:\n game0flife [options]\n\n
54
+ \ Options:\n --pattern=<acorn|diehard|r_pentomino|simple_spaceship>\n
55
+ \ --framerate=60\n --pattern_x=20 (60x60 Frame)\n --pattern_y=20
56
+ \ (60x60 Frame)\n\n"
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 2.7.2
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements:
71
+ - libsdl2 | SDL2
72
+ rubygems_version: 3.1.4
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Game Of Life on SDL2
76
+ test_files: []