Skip to content

Instantly share code, notes, and snippets.

@DonSchado
Last active October 27, 2021 06:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DonSchado/190577197e744704885e0d39e1e1adf1 to your computer and use it in GitHub Desktop.
Save DonSchado/190577197e744704885e0d39e1e1adf1 to your computer and use it in GitHub Desktop.
Game of life variation
class WoodOfLife
include Enumerable
ROWS = 50
COLUMNS = 50
EXAMPLE = Array.new(ROWS * COLUMNS) { rand(2) }.join
attr_reader :cells, :rows, :columns
def initialize(options = {})
@rows = (options[:rows] || ROWS).to_i.clamp(1, ROWS)
@columns = (options[:columns] || COLUMNS).to_i.clamp(1, COLUMNS)
@cells = (options[:state] || EXAMPLE).ljust(board_size, '0')[0...board_size].chars.map(&:to_i)
end
def generation
if @cells.none?(&burning?)
@cells[rand(board_size)] = 2 # 🙀
end
@cells = cells.each_with_index.map do |cell, index|
rules(cell_state: cell, neighbors_count: neighbors_count(index))
end
self
end
def each(&block)
cells.each(&block)
end
def board_size
columns * rows
end
def burning?
->(c) { c == 2 }
end
private
def rules(cell_state:, neighbors_count:)
return 3 if cell_state == 1 && neighbors_count >= 3 # whoa too much fire, let's fight!!!
return 4 if cell_state == 3 # phew we cleared...
return 5 if cell_state == 4 # but sadly this tree is dead
return 2 if cell_state == 1 && neighbors_count > 1 # oh noes fire!!!
cell_state
end
# nw n ne
# w [i] e
# sw s se
def neighbors_count(i)
n = relative(i-columns, 0)
s = relative(i+columns, 0)
e = relative(i, +1)
w = relative(i, -1)
nw = relative(n, -1)
ne = relative(n, +1)
sw = relative(s, -1)
se = relative(s, +1)
cells.values_at(*[n, nw, ne, e, w, s, sw, se].compact).select(&burning?).sum
end
# enforces boundaries at the "board borders"
def relative(reference_point, distance)
return if reference_point.nil? # there is no cell
return if (reference_point + distance) >= board_size # out of bound +
return if (reference_point + distance).negative? # out of bound -
# calculate possible move
reference_point/columns == (reference_point + distance)/columns ? (reference_point + distance) : nil
end
end
wood = WoodOfLife.new
loop do
system "clear"
wood.each.with_index(1) do |cell, i|
case cell
when 0
print ' '
when 1
print '🌲'
when 2
print '🔥'
when 3
print '🚒'
when 4
print '💧'
when 5
print ' '
end
if i % wood.columns == 0
print "\n"
end
end
sleep 0.2
wood.generation
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment