Files
infinsweeper/game_logic.rb
2025-06-21 17:38:17 +03:00

101 lines
2.4 KiB
Ruby

require "xxhash"
# Game logic main class
class GameLogic
@seed = rand(111_111..999_999)
@pos = {
board: {},
lost: {},
cache: {},
}
# Returns a pseudorandom number between 0 and 100
def self.hash(data)
XXhash.xxh32(data.to_s, @seed) % 100
end
def self.reset_pos
@pos.each_value(&:clear)
end
def self.reveal(g_x, g_y)
l_x = ((g_x % 9) + 9) % 9
l_y = ((g_y % 9) + 9) % 9
s_x = (g_x / 9).floor
s_y = (g_y / 9).floor
return if @pos.board["#{s_x}:#{s_y}"] == true
build_sector(s_x, s_y) if @pos.board["#{s_x}:#{s_y}"].nil?
return if @pos.board["#{s_x}:#{s_y}"][l_x][l_y][1] || @pos.board["#{s_x}:#{s_y}"][l_x][l_y][2]
if @pos.board["#{s_x}:#{s_y}"][l_x][l_y][0] == -1
@pos.lost["#{s_x}:#{s_y}"] = 1
elsif @pos.board["#{s_x}:#{s_y}"][l_x][l_y][0].zero?
(-1..1).each do |x|
(-1..1).each do |y|
next if x.zero? && y.zero?
reveal(g_x + x, g_y + y)
end
end
else
@pos.board["#{s_x}:#{s_y}"][l_x][l_y][1] = true
end
@pos.board["#{s_x}:#{s_y}"] = true if solved?(s_x, s_y)
end
def self.solved?(s_x, s_y)
(0..8).each do |l_x|
(0..8).each do |l_y|
return false if !@pos.board["#{s_x}:#{s_y}"][l_x][l_y][1] && @pos.board["#{s_x}:#{s_y}"][l_x][l_y][0] != -1
end
end
true
end
def self.count(g_x, g_y)
sum = 0
(-1..1).each do |x|
(-1..1).each do |y|
next if x.zero? && y.zero?
sum += 1 if mine?(g_x + x, g_y + y)
end
end
sum
end
def self.build_sector(s_x, s_y)
@pos.board["#{s_x}:#{s_y}"] = []
(0..8).each do |l_x|
@pos.board["#{s_x}:#{s_y}"][l_x] = []
(0..8).each do |l_y|
g_x = l_x + s_x * 9
g_y = l_y + s_y * 9
@pos.board["#{s_x}:#{s_y}"][l_x][l_y] = [
mine?(g_x, g_y) ? -1 : count(g_x, g_y),
false, false,
]
end
end
end
def self.build_cache(s_x, s_y)
return if @pos.cache["#{s_x}:#{s_y}"]
return unless @pos.board["#{s_x}:#{s_y}"] == 1
@pos.cache["#{s_x}:#{s_y}"] = []
(0..8).each do |l_x|
@pos.cache["#{s_x}:#{s_y}"][l_x] = []
(0..8).each do |l_y|
g_x = l_x + s_x * 9
g_y = l_y + s_y * 9
@pos.cache["#{s_x}:#{s_y}"][l_x][l_y] =
mine?(g_x, g_y) ? [-1, false, true] : [count(g_x, g_y), true, false]
end
end
end
def self.mine?(g_x, g_y)
g_x == 4 || g_y == 4 ? false : hash("#{g_x}:#{g_y}") < 17
end
end