-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame.rb
122 lines (94 loc) · 2.63 KB
/
game.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# frozen_string_literal: true
# it's the cell
class Cell
attr_reader :alive, :neighbours
def initialize(alive: false)
@alive = api_alive_to_internal(alive)
end
def alive=(alive)
@alive = api_alive_to_internal(alive)
end
def alive?
internal_alive_to_api(@alive)
end
def add_neighbours(neighbours)
@neighbours = neighbours
end
def living_neighbour_count
@neighbours.map(&:alive).sum
end
def cache_to_live_or_die
self.cached_live_or_die = live_or_die?
end
def tick
self.alive = cached_live_or_die.nil? ? live_or_die? : cached_live_or_die
self.cached_live_or_die = nil
end
def inspect
to_s
end
private
attr_accessor :cached_live_or_die
def live_or_die?
if alive?
live_or_die_when_alive?
else
live_or_die_when_dead?
end
end
def live_or_die_when_alive?
return true if [2, 3].include?(living_neighbour_count)
false
end
def live_or_die_when_dead?
return true if living_neighbour_count == 3
false
end
def api_alive_to_internal(alive)
alive ? 1 : 0
end
def internal_alive_to_api(internal_alive)
internal_alive == 1
end
end
# This class will run the game
class Game
def initialize(board)
@board = board_with_introduced_neighbours(board)
end
def cell_alive?(x:, y:) # rubocop:disable Naming/MethodParameterName
@board[x][y].alive?
end
def cell_at(x:, y:) # rubocop:disable Naming/MethodParameterName
cell_at_for_board(board: @board, x: x, y: y)
end
def tick
@board.each { |col| col.each(&:cache_to_live_or_die) }
@board.each { |col| col.each(&:tick) } # rubocop:disable Style/CombinableLoops
end
private
def cell_at_for_board(board:, x:, y:) # rubocop:disable Naming/MethodParameterName
return nil if x.negative? || x > (board.size - 1)
return nil if y.negative? || y > (board[x].size - 1)
board[x][y]
end
def board_with_introduced_neighbours(board)
board.each.with_index do |col, x|
col.each.with_index do |cell, y|
cell.add_neighbours(neighbours_for_cell_at(board: board, x: x, y: y))
end
end
end
def neighbours_for_cell_at(board:, x:, y:) # rubocop:disable Naming/MethodParameterName
neighbour_coords_at(x: x, y: y)
.map { |coord| cell_at_for_board(board: board, x: coord[:x], y: coord[:y]) }
.compact
end
def neighbour_coords_at(x:, y:) # rubocop:disable Naming/MethodParameterName
[
{ x: x - 1, y: y - 1 }, { x: x, y: y - 1 }, { x: x + 1, y: y - 1 },
{ x: x - 1, y: y }, { x: x + 1, y: y },
{ x: x - 1, y: y + 1 }, { x: x, y: y + 1 }, { x: x + 1, y: y + 1 }
]
end
end