Skip to content

Instantly share code, notes, and snippets.

@marmeladze
Last active May 31, 2023 14:16
Show Gist options
  • Select an option

  • Save marmeladze/cfe009e6c4f287b39e81fc1cbaa86076 to your computer and use it in GitHub Desktop.

Select an option

Save marmeladze/cfe009e6c4f287b39e81fc1cbaa86076 to your computer and use it in GitHub Desktop.
Cat Puzzle
require 'securerandom'
class Box
attr_reader :order, :filled
def initialize(order)
@order = order
@filled = false
end
def fill!
@filled = true
end
def empty!
@filled = false
end
def filled?
@filled
end
end
class Reality
attr_reader :boxes
def initialize(box_count)
@box_count = box_count
create_boxes!
fill_random_box!
generate_possible_steps!
end
def create_boxes!
@boxes = 1.upto(@box_count).map { |i| Box.new(i) }
end
def fill_random_box!
@boxes.sample.fill!
end
def filled_box
@filled_box = @boxes.find { |box| box.filled? }
end
def filled_box_order
@filled_box_order = filled_box.order
end
def possible_moves
@moves = @possible_moves[filled_box_order-1]
end
def generate_possible_steps!
@possible_moves ||= (1..@box_count).each_with_object([]) do |i, acc|
acc << case i
when 1 then [2]
when @box_count then [i-1]
else
[i-1, i+1]
end
end
end
def move_cat
box_to_fill_order = possible_moves.sample
@boxes.find { |box| box.order == filled_box_order }.empty!
@boxes.find { |box| box.order == box_to_fill_order }.fill!
end
end
class RealityActions
def self.new(box_count)
@reality = Reality.new(box_count)
end
def self.build_reality(box_count)
@reality = new(box_count)
end
def self.move_cat
@reality.move_cat
end
def self.filled_slot
@reality.filled_box_order
end
end
class DummySimulator
def initialize(box_count)
@box_count = box_count || 5
RealityActions.build_reality(@box_count)
end
def run(iterations)
1.upto iterations do |i|
run_iteration
end
end
private
def run_iteration
print "\e[2J\e[f"
RealityActions.move_cat
pointer = RealityActions.filled_slot
board = [" "]*@box_count
board[pointer-1] = "\u{1F408}"
print board
puts
sleep(1)
end
end
class GameSimulator
def initialize(game_logs)
@game_logs = game_logs
end
def build
@game_logs.each do |log|
draw_screen(log)
end
end
def draw_screen(log)
cat = "\u{1F408}"
win = "\u{1F92B}"
miss = "\u{1F595}"
cat_position = log[:filled_box]
player_guess = log[:player_guess]
box_count =log[:box_count] || 5
board = [" "]*box_count
board[cat_position-1] = cat
just = 5*(player_guess-1)+3
print "\e[2J\e[f"
if cat_position == player_guess
print "#{board}\n#{win.rjust(just)}"
else
print "#{board}\n#{miss.rjust(just)}"
end
puts
sleep(1)
end
end
class GameLogs
def initialize(uuid)
@uuid = uuid
end
def fetch
f = File.open("#{@uuid}.game.log", 'r')
contents = f.read()
f.close
logs = contents.split("\n")
logs.map! {|e| eval(e) }
end
end
class Game
def initialize(box_count)
@box_count = box_count
RealityActions.build_reality(@box_count)
@finished = false
@selection_range = 1..@box_count
@game_log = []
end
def run
i = 0
puts "Choose a box from 1 to #{@box_count}"
until @finished
board = ["\u{1F961}"]*@box_count
# board_hint =
pointer = RealityActions.filled_slot
player_input = gets.chomp.to_i
if @selection_range.include? player_input
if player_input == pointer
board[pointer-1] = "\u{1F408} \u{1F92B}"
print board
puts "LUCKY WINNER"
@finished = true
else
board[player_input-1] = "\u{1F595}"
print board
puts "MISS"
sleep(0.5)
end
i+=1
RealityActions.move_cat
log(i, pointer, player_input)
end
end
print_and_save_game_log
end
private
def log(i, pointer, player_input)
@game_log << {iteration: i, filled_box: pointer, player_guess: player_input, box_count: @box_count}
end
def print_and_save_game_log
file_name = "#{SecureRandom.uuid}.game.log"
File.open(file_name, "w") do |f|
@game_log.each do |iteration|
f.puts iteration
end
end
print "\e[2J\e[f"
puts "Game logs saved to #{file_name}. Would you like to watch? Y/N"
answer = gets.chomp
unless answer == 'Y'
return
end
simulate_last_game
end
end
def play_game
puts "How much boxes"
f = gets.chomp.to_i
print "\e[2J\e[f"
if f > 0
Game.new(f).run
end
end
def last_game_logs
Dir['*.game.log'].sort_by do |f|
File::Stat.new(f).birthtime
end.last
end
def simulate_last_game
id = File.basename last_game_logs, '.game.log'
simulate_game(id)
end
def simulate_game(id)
logs = GameLogs.new(id).fetch
GameSimulator.new(logs).build
end
def run_dummy_simulator(boxes, iterations)
DummySimulator.new(boxes).run(iterations)
end
play_game
# simulate_game('1eb31c9c-3ce7-4671-91eb-318f0599d3ed')
# run_dummy_simulator(7, 20)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment