Something went wrong. Try again.
Code for the Advent of Code event
aoc advent-of-code
Something went wrong. Try again.
2.7 kB · 147 lines
Ruby
at rust
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148#!/usr/bin/env ruby# frozen_string_literal: true
require 'curses'require 'matrix'
require_relative '../../../lib/aoc/intcode/cpu'
class Vector def x; self[0]; end def y; self[1]; endend
DEBUG = ENV.fetch('DEBUG', nil)
PATH = ARGV.first || 'input'
TILE_TYPES = { 0 => :empty, 1 => :wall, 2 => :block, 3 => :paddle, 4 => :ball}.freeze
# TILE_SPRITES = {# empty: ' ',# wall: '█',# block: '▒',# paddle: '━',# ball: '●'# }
TILE_SPRITES = { empty: ' ', wall: '#', block: 'O', paddle: '-', ball: '*'}.freeze
# grid = {}# bounds = Struct.new(:top, :bottom, :left, :right).new(0, 0, 0, 0)
class Game attr_reader :grid, :score
def initialize(cpu, play: false) @cpu = cpu @bounds = Struct.new(:top, :bottom, :left, :right).new(0, 0, 0, 0) @grid = Hash.new :empty @score = 0 @play = play @cpu.memory[0] = 2 if play end
def run! Curses.clear
step!
return unless @play
step! while count(:block) > 0 end
def step! @cpu.run! update! draw end
def update! @cpu.output.each_slice(3).each do |(x, y, value)| pos = Vector[x, y]
if x == -1 && y == 0 @score = value else tile = TILE_TYPES[value] @grid[pos] = tile update_bounds! pos @ball_pos = pos if tile == :ball @paddle_pos = pos if tile == :paddle end end
@cpu.clear_output! @cpu.input! @ball_pos.x <=> @paddle_pos.x end
def update_bounds!(pos) @bounds.top = pos.y if pos.y < @bounds.top @bounds.bottom = pos.y if pos.y > @bounds.bottom @bounds.left = pos.x if pos.x < @bounds.left @bounds.right = pos.x if pos.x > @bounds.right end
def draw Curses.setpos 0, 0 Curses.addstr "SCORE: #{@score}" (@bounds.top..@bounds.bottom).each do |y| (@bounds.left..@bounds.right).each do |x| pos = Vector[x, y] raise 'Pos is null' if pos.nil? tile = @grid[pos] raise "Tile is null at #{pos}" if tile.nil? sprite = TILE_SPRITES[tile] raise "Sprite for #{tile} is null at #{pos}" if sprite.nil? Curses.setpos y + 1, x Curses.addch sprite end end
Curses.refresh # sleep 0.5 # Curses.getch end
def count(type) @grid.values.count(type) endend
cpu = AoC::Intcode::CPU.new.print_output!(false).load!(PATH)cpu2 = cpu.dup
Curses.init_screenbegin Curses.noecho Curses.cbreak Curses.curs_set 0
game = Game.new cpu game.run!
game2 = Game.new cpu2, true game2.run!ensure Curses.close_screenend
puts "Part 1: #{game.count :block}"puts "Part 2: #{game2.score}"
# require 'pry'# binding.pry