class Cabinet: def __init__(self, filename): '''Create the arcade cabinet, and load up the file.''' self.input_buffer = list() self.output_buffer = list() self.intputer = Intputer(self.input_buffer, self.output_buffer) self.intputer.load_program(filename) self.tiles = dict() def run(self): '''Run the game''' while self.intputer.running: self.intputer.run(pause_for_input=True) while len(self.output_buffer) >= 3: self.process_tilebuffer() def process_tilebuffer(self): '''Pull the next 3 ints out of the output buffer and update the tiles.''' if len(self.output_buffer) < 3: raise RuntimeError('Not enough values in the buffer to process a tile.') col, row, tile = self.output_buffer[:3] self.output_buffer = self.output_buffer[3:] self.tiles[(row, col)] = tile
robot_location = (robot_location[0] + moves[robot_direction][0], robot_location[1] + moves[robot_direction][1]) def process_output(): while output_buffer: paintPanel(robot_location, output_buffer.pop(0)) rotate(output_buffer.pop(0)) move() def read_camera(): input_buffer.append(readPanel(robot_location)) paintPanel((0,0), 1) # Second star - starting panel is white read_camera() while intputer.running: intputer.run(pause_for_input=True) process_output() if intputer.running: read_camera() # How big is the resulting message? min_row = min([pos[0] for pos in panels]) max_row = max([pos[0] for pos in panels]) min_col = min([pos[1] for pos in panels]) max_col = max([pos[1] for pos in panels]) print('Second star answer: ') for i in range(max_row, min_row-1, -1): outline = [] for j in range(min_col, max_col+1): outline.append('#' if panels.get((i,j),0) else ' ')
class Droidmap: movemap = { 'N': {"dircode": 1, "dirmove": (-1, 0)}, 'S': {"dircode": 2, "dirmove": ( 1, 0)}, 'W': {"dircode": 3, "dirmove": ( 0,-1)}, 'E': {"dircode": 4, "dirmove": ( 0, 1)} } directions = ('N', 'E', 'S', 'W') map_symbols = { None: ' ', 0: '#', 1: '.', 2: '0' } def __init__(self, data): self.droid_loc = (0,0) self.last_move = 0 self.map = {(0,0):1} self.input_buffer = list() self.output_buffer = list() self.intputer = Intputer(input_buffer=self.input_buffer, output_buffer=self.output_buffer, name="Droid") self.intputer.load_program(data) self.move_count = 1 self.o2at = None self.current_direction = 0 def rightside_explore(self): '''Traverse the entire map keeping the wall to our right. Assuming the maze is a closed space, we'll eventually loop back to the starting point after having explored the entire maze.''' while not (self.droid_loc == (0,0) and self.move_count > 20): # Try to move forward. result = self.one_move(self.directions[self.current_direction]) # Blocked? Turn left. if not result: self.current_direction = (self.current_direction - 1) % 4 # Free? Turn right. else: self.current_direction = (self.current_direction + 1) % 4 def one_move(self, move): self.move_count += 1 self.last_move = move self.input_buffer.append(self.movemap[move]["dircode"]) self.intputer.run(pause_for_input=True) if self.output_buffer: result = self.handle_output() return result return None def run_random(self): '''Not used - makes random moves until it finds the O2''' self.random_move() while self.intputer.running and self.move_count > 0: self.intputer.run(pause_for_input=True) if self.output_buffer: self.handle_output() if self.o2at: self.move_count -= 1 else: self.move_count += 1 self.random_move() def move_input(self): '''Not used. Originally for manual exploration of the map.''' move = input('Enter a move: N, S, E, W: ') move = move.upper() self.last_move = move self.input_buffer.append(self.movemap[move]["dircode"]) def random_move(self): '''Not used, but this was a first method to test exploring the map. It works, but takes too long.''' move = random.choice(['N','S','E','W']) self.last_move = move self.input_buffer.append(self.movemap[move]["dircode"]) def handle_output(self): while self.output_buffer: status = self.output_buffer.pop(0) newloc = (self.droid_loc[0] + self.movemap[self.last_move]["dirmove"][0], self.droid_loc[1] + self.movemap[self.last_move]["dirmove"][1]) if status == 0: self.map[newloc] = 0 elif status == 1: self.map[newloc] = 1 self.droid_loc = newloc elif status == 2: self.map[newloc] = 2 self.droid_loc = newloc if not self.o2at: self.o2at = newloc print(f"OXYGEN FOUND AT LOCATION {newloc} on move {self.move_count}") else: raise RuntimeError(f"Unexpected status value encountered: {status}") return status def print_map(self): print('========') min_row, max_row, min_col, max_col = 0, 0, 0, 0 for loc in self.map: min_row = min(loc[0], min_row) max_row = max(loc[0], max_row) min_col = min(loc[1], min_col) max_col = max(loc[1], max_col) for i in range(min_row, max_row+1): output_row = [] for j in range(min_col, max_col+1): if (i, j) == self.droid_loc: output_row.append('D') elif (i, j) == (0, 0): output_row.append('X') else: output_row.append(self.map_symbols[self.map.get((i,j), None)]) print(''.join(output_row)) print(f'Number of moves to explore maze: {self.move_count}') def possible_moves(self, loc): for move in self.movemap.values(): tryloc = (loc[0] + move['dirmove'][0], loc[1] + move['dirmove'][1]) if self.map.get(tryloc, 0): yield tryloc def minmoves_to_o2(self): shell_counts = 0 move_shell = set([self.o2at]) visited_locations = set([self.o2at]) while move_shell: shell_counts += 1 next_move_shell = set() for loc in move_shell: for tryloc in self.possible_moves(loc): if tryloc not in visited_locations: if tryloc == (0,0): print(f'Path to (0,0) found in {shell_counts} moves') return next_move_shell.add(tryloc) visited_locations.add(tryloc) move_shell = next_move_shell raise RuntimeError('Never found the origin.')
class Cabinet: tilemap = {0: ' ', 1: '#', 2: '@', 3: '=', 4: 'o'} def __init__(self, filename): '''Create the arcade cabinet, and load up the file.''' self.input_buffer = list() self.output_buffer = list() self.intputer = Intputer(self.input_buffer, self.output_buffer) self.intputer.load_program(filename) self.tiles = dict() self.score = 0 def coindrop(self): self.intputer.memory[0] = 2 def run(self): '''Run the game''' while self.intputer.running: self.intputer.run(pause_for_input=True) while len(self.output_buffer) >= 3: self.process_tilebuffer() self.make_move() # self.print_screen() def make_move(self): '''Figure out what move we should make, and make it.''' # Compare the columns of the ball and paddle ball_col = [pos for pos, tile in self.tiles.items() if tile == 4][0][1] paddle_col = [pos for pos, tile in self.tiles.items() if tile == 3][0][1] move = 0 if ball_col < paddle_col: move = -1 elif ball_col > paddle_col: move = 1 self.input_buffer.append(move) def process_tilebuffer(self): '''Pull the next 3 ints out of the output buffer and update the tiles.''' if len(self.output_buffer) < 3: raise RuntimeError( 'Not enough values in the buffer to process a tile.') col = self.output_buffer.pop(0) row = self.output_buffer.pop(0) tile = self.output_buffer.pop(0) if col == -1 and row == 0: self.score = tile else: self.tiles[(row, col)] = tile def print_screen(self): '''Print out the screen memory''' print(f'Score: {self.score}') min_row = 0 max_row = 0 min_col = 0 max_col = 0 for loc in self.tiles: min_row = min(min_row, loc[0]) max_row = max(max_row, loc[0]) min_col = min(min_col, loc[1]) max_col = max(max_col, loc[1]) for row in range(min_row, max_row + 1): output_row = [] for col in range(min_col, max_col + 1): tile = self.tiles.get((row, col), 0) output_row.append(self.tilemap[tile]) print(''.join(output_row))
from intputer import Intputer program = [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ] program = [1102, 34915192, 34915192, 7, 4, 7, 99, 0] program = [104, 1125899906842624, 99] program = 'a09_input.txt' input_buffer = [1] output_buffer = [] intputer = Intputer(input_buffer=input_buffer, output_buffer=output_buffer) # intputer = Intputer(output_buffer=output_buffer) intputer.load_program(program) intputer.run() print(output_buffer)