def main_rendered(screen: Any, program: List[int]) -> None: ''' Navigate through the maze to find the end and display progress on screen. ''' curses.curs_set(0) # A dict, keyed on coordinates, with the number of times each direction has been traversed exploration_history: Dict[Tuple[int, int], int] = defaultdict(lambda: 0) # A dict, keyed on coordinates, with the character to render for that location maze_map: Dict[Tuple[int, int], str] = defaultdict(lambda: UNKNOWN) current_location: Tuple[int, int] = (0, 0) status: int = None # used to store result of the last instruction exploration_history[current_location] += 1 maze_map[current_location] = START robot = IntcodeComputer(program) steps = 0 while True: render_scene(screen, current_location, maze_map) direction_to_move = get_next_direction(current_location, exploration_history) status = robot.run_until_input_required(direction_to_move)[0] if status == HIT_WALL: exploration_history[destination_coordinate( current_location, direction_to_move)] = LARGE_NUMBER maze_map[destination_coordinate(current_location, direction_to_move)] = WALL elif status == MOVED: current_location = destination_coordinate(current_location, direction_to_move) exploration_history[current_location] += 1 if maze_map[current_location] == UNKNOWN: maze_map[current_location] = PATH else: # GOAL current_location = destination_coordinate(current_location, direction_to_move) exploration_history[current_location] += 1 maze_map[current_location] = GOAL steps += 1 time.sleep(1 / REFRESH_RATE) if steps % 100 == 0 and is_exploration_complete(maze_map): break serialize_maze(maze_map, 'day15_maze_map.json') render_scene(screen, (0, 0), maze_map) screen.addstr(0, 0, ('{:^' + str(NX) + 's}').format('MAZE MAPPED!')) screen.getch()
class ArcadeCabinet(object): tile_rendering = { 0: ' ', # Blank 1: '$', # Wall 2: '#', # Block 3: '-', # Paddle 4: 'o' # Ball } def __init__(self, screen: Any, program: List[int], free_play: bool=True) -> None: if free_play: tmp = program.copy() tmp[0] = 2 else: tmp = program.copy() self.score: int = 0 self.paddle_x_position = -1 self.ball_x_position = -1 self.computer = IntcodeComputer(tmp) self.screen = screen initial_screen = self.computer.run_until_input_required() self.render_screen(initial_screen) curses.curs_set(0) def render_screen(self, tiles: List[int]) -> None: for i in range(0, len(tiles), 3): if tiles[i] == -1 and tiles[i+1] == 0: new_score = tiles[i+2] if new_score > self.score: self.score = new_score self.screen.addstr(0, 0, f'Score: {self.score:>10}') else: self.screen.addch( tiles[i+1] + 1, tiles[i], self.tile_rendering[tiles[i+2]] ) if tiles[i+2] == 3: self.paddle_x_position = tiles[i] if tiles[i+2] == 4: self.ball_x_position = tiles[i] self.screen.refresh() def game_loop(self, bot_player: bool=False) -> None: while True: if not bot_player: key = self.screen.getch() if key == curses.KEY_LEFT: input_value = -1 elif key == curses.KEY_RIGHT: input_value = 1 else: input_value = 0 else: diff = self.ball_x_position - self.paddle_x_position if diff > 0: input_value = 1 elif diff < 0: input_value = -1 else: input_value = 0 time.sleep(0.01) tiles = self.computer.run_until_input_required(input_value) if tiles is None: self.screen.addstr(18, 13, f'GAME OVER') self.screen.addstr(19, 13, f'SCORE: {self.score}') key = self.screen.getch() break else: self.render_screen(tiles)