class EHPR(): def __init__(self, program): self.painted = defaultdict(int) self.position = Position(0,0) self.direction = Direction.Up self.computer = IntcodeComputer(program, [], "Emergency Hull Painting Robot", 0) def set_start_color(self, color): self.painted[self.position] = color def move(self, command): new_direction = (Direction(((self.direction.value + 1) % 4)) if command else Direction(((self.direction.value - 1) % 4))) new_position = Position(*(sum(x) for x in zip(self.position, movement[new_direction]))) self.direction = new_direction self.position = new_position def paint_square(self, color): self.painted[self.position] = color def execute_step(self): self.computer.add_input(self.painted[self.position]) self.computer.run_program() output = self.computer.get_output() color, command = output[-2:] self.paint_square(color) self.move(command)
class ArcadeCabinet(): def __init__(self, program, free_play=False, auto=False, display=True): if free_play: program = program[:] program[0] = 2 self.computer = IntcodeComputer(program, [], "Arcade Cabinet") self.gamestate = dict() self.ball, self.tile = None, None self.auto = auto self.display = display def draw_screen(self): max_x = max(x for x, y in self.gamestate.keys()) max_y = max(y for x, y in self.gamestate.keys()) score = self.gamestate[(-1, 0)] if (-1, 0) in self.gamestate else 0 printstr = "\tSCORE:\t %i\n" % score for y in range(max_y + 1): for x in range(max_x + 1): printstr = printstr + "%s" % tiles[self.gamestate[(x, y)]] printstr = printstr + "\n" sys.stdout.write(printstr) def parse_instruction(self, instruction): x, y, tile = instruction self.gamestate[(x, y)] = tile if tile == 4: self.ball = x elif tile == 3: self.tile = x def joystick(self, key='n'): if keyboard.is_pressed('a') or key == 'a': self.computer.add_input(-1) elif keyboard.is_pressed('d') or key == 'd': self.computer.add_input(1) elif keyboard.is_pressed('s') or key == 's': self.computer.add_input(0) def self_play(self): if self.tile > self.ball: return 'a' elif self.tile < self.ball: return 'd' else: return 's' def score_counter(self): score = self.gamestate[(-1, 0)] if (-1, 0) in self.gamestate else 0 sys.stdout.write("\r") sys.stdout.flush() sys.stdout.write("Score: %i" % score) def run_game(self): while not self.computer.has_stopped(): output = self.computer.run_program() for instruction in chunks(output, 3): self.parse_instruction(instruction) if self.display: self.draw_screen() time.sleep(0.07) else: self.score_counter() self.computer.input_l.clear() key = self.self_play() if self.auto else None self.joystick(key) sys.stdout.write('\n') self.draw_screen()
class RepairDroid(): def __init__(self, program, visualize=0): self.computer = IntcodeComputer(program, [], "Arcade Cabinet") self.areamap = dict() self.visualize = visualize self.startpos = Position(0,0) self.areamap[self.startpos] = Field(self.startpos, 1, -1) self.currentpos = self.startpos def move_droid(self, direction): move = movement[direction] new_pos = Position(self.currentpos.x + move[0], self.currentpos.y + move[1]) self.computer.add_input(direction.value) output = self.computer.run_program() if new_pos not in self.areamap: new_field = Field(new_pos, output[-1], self.areamap[self.currentpos].dist) self.areamap[new_pos] = new_field if new_field.type == FieldType.WALL: return False else: self.currentpos = new_pos return True elif self.areamap[new_pos].type != FieldType.WALL: if self.areamap[new_pos].dist < self.areamap[self.currentpos].dist-1: # we found a shorter path to the current position self.areamap[self.currentpos].update_dist(self.areamap[new_pos].dist+1) self.currentpos = new_pos return False else: return False def draw_map(self): min_x = min(x for x,y in self.areamap.keys()) max_x = max(x for x,y in self.areamap.keys()) min_y = min(y for x,y in self.areamap.keys()) max_y = max(y for x,y in self.areamap.keys()) x_range = max_x - min_x y_range = max_y - min_y full_map = "" for y in range(y_range+1): for x in range(x_range+1): position = Position(x+min_x, y+min_y) if position == self.currentpos: full_map = full_map + "D" elif position not in self.areamap: full_map = full_map + "#" elif self.areamap[position].type == FieldType.FIELD: full_map = full_map + " " elif self.areamap[position].type == FieldType.WALL: full_map = full_map + "|" elif self.areamap[position].type == FieldType.OSYS: full_map = full_map + "X" elif self.areamap[position].type == FieldType.OXY: full_map = full_map + "O" full_map = full_map + "\n" full_map = full_map + "\n" print(full_map) def traverse_grid(self): directions = [Direction.EAST, Direction.SOUTH, Direction.NORTH, Direction.WEST] steps = deque(directions) i = 0 while steps: i+=1 next_move = steps.popleft() if self.visualize: time.sleep(0.2) print("Step: %i" % i) self.draw_map() if self.move_droid(next_move): prev = opposite[next_move] steps.appendleft(prev) move_order = directions[:] move_order.remove(prev) for entry in reversed(move_order): steps.appendleft(entry) else: continue self.draw_map()