def play(program, coins=2, render=False): if render: print("\033[2J") cpu = IntCodeCPU(program) cpu.poke(0, coins) interrupt = cpu.run() if interrupt != InterruptCode.WAITING_ON_INPUT: raise ValueError(f"Unexpected program state: Interrupt = {interrupt}") gs = GameState.init(cpu.pop_output()) while True: delta = gs.ball_x - gs.paddle_x if delta > 0: in_ = (1, ) elif delta < 0: in_ = (-1, ) else: in_ = (0, ) res = cpu.run(in_) gs.update(cpu.pop_output()) if render: gs.render() sleep(0.015) if res is None: break return gs.score
def test_relative_mode_addressing(self): program = [ int(i) for i in "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99".split( ",") ] cpu = IntCodeCPU(program[:]) cpu.run() self.assertEqual(program, cpu.pop_output())
def get_thruster_output(program, phase_settings): outputs = [] for ps in phase_settings: inputs = (ps, outputs[0] if outputs else 0) runner = IntCodeCPU(program, ps) runner.run(inputs) outputs = runner.pop_output() return outputs[0]
def get_blocks_after_first_run(program): cpu = IntCodeCPU(program) cpu.run() output = cpu.pop_output() c = 0 for i in range(2, len(output), 3): if output[i] == 2: c += 1 return c
def build(cls, program): cpu = IntCodeCPU(program) res = cpu.run() if res is not None: raise ValueError(f"CPU raised an interrupt: {res}") grid = "".join([chr(i) for i in cpu.pop_output()]) grid = [list(r) for r in grid.split("\n") if r] direction_chars = {d.value for d in Direction} for x, y in itertools.product(range(len(grid[0])), range(len(grid))): if grid[y][x] in direction_chars: pos = (x, y) dir_ = Direction(grid[y][x]) grid[y][x] = "#" break else: raise ValueError("Vacuum not found") return cls(grid, pos, dir_)
def run_robot(program, initial_coords, initial_color): panels = {initial_coords: Panel(*initial_coords, initial_color)} robot = Robot(*initial_coords) cpu = IntCodeCPU(program) while True: p = panels.get(robot.position) if not p: p = Panel(*robot.position) panels[robot.position] = p res = cpu.run((p.color.value, )) if res == InterruptCode.WAITING_ON_INPUT: c, td = cpu.pop_output() p.paint(Color(c)) robot.turn(TurnDirection(td)) robot.move_forward() else: break return panels
def generate_floor(program): robot = Robot(0, 0, Direction.UP) floor = Map(robot) cpu = IntCodeCPU(program) interrupt = cpu.run() if interrupt != InterruptCode.WAITING_ON_INPUT: raise ValueError(f"Unexpected program state: Interrupt = {interrupt}") while True: res = cpu.run((robot.direction,)) out = cpu.pop_output() if len(out) > 1: raise ValueError(f"Output too long: {out}") out = out[0] new_pos = robot.next_pos() if out == 0: floor.set_tile(new_pos.x, new_pos.y, Tile.WALL) robot.turn_left() elif out == 1: floor.set_tile(new_pos.x, new_pos.y, Tile.EMPTY) robot.set_pos(new_pos) robot.turn_right() elif out == 2: floor.set_tile(new_pos.x, new_pos.y, Tile.OXYGEN) floor.oxy_pos = Point(new_pos.x, new_pos.y) robot.set_pos(new_pos) robot.turn_right() else: raise ValueError(f"Invalid output: {out}") if res is None or robot.pos == floor.orig: break return floor
def get_diagnostic_code(program, system_id): r = IntCodeCPU(program) r.run((system_id, )) return r.pop_output()[-1]
def get_boost_keycode(program): cpu = IntCodeCPU(program) cpu.run((1,)) output = cpu.pop_output() assert len(output) == 1 return output[0]
def get_coords(program): cpu = IntCodeCPU(program) cpu.run((2,)) output = cpu.pop_output() assert len(output) == 1 return output[0]
def test_write(self): program = [4, 3, 99, 42] cpu = IntCodeCPU(program) cpu.run() self.assertEqual([42], cpu.pop_output())
def test_output_middle_number(self): program = "104,1125899906842624,99" cpu = IntCodeCPU(program[:]) cpu.run() self.assertEqual([1125899906842624], cpu.pop_output())
def test_big_numbers(self): program = "1102,34915192,34915192,7,4,7,99,0" cpu = IntCodeCPU(program) cpu.run() self.assertEqual([1219070632396864], cpu.pop_output())