game0flife 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []