def check_the_absence_of_a_wall(self, coordinates, direction): """ Check the absence of a wall in the direction of the move. coordinates: tuple of x and y coordinate direction: object of Direction class Return a boolean. True - There isn't wall, robot can move. False - There is wall, robot can't move. """ old_tiles = self.get_tiles(coordinates) # Current tile: Check wall in the direction of next move. for tile in old_tiles: move_from = tile.can_move_from(direction) if not move_from: # Current tile: There is a wall in the direction of the move. return False # There is no wall, so get next coordinates. next_coordinates = get_next_coordinates(coordinates, direction) # Get new list of tiles. new_tiles = self.get_tiles(next_coordinates) # Check wall on the next tile in the direction of the move. for tile in new_tiles: move_to = tile.can_move_to(direction) if not move_to: # Next tile: There is a wall in the direction of the move. return False return True
def shoot(self, state): """ Shoot in robot's direction. If there is a wall on the way, the robot's laser stops (it can't pass it). If there is a robot on the way, he gets shot and the laser ends there. If a robot has activated Power Down for this register, he can't shoot. The check is performed from robot's position till the end of the board in robot's direction. """ if not self.power_down: distance_till_end = self.get_distance_to_board_end(state) # First coordinates are robot's coordinates - wall must be checked next_coordinates = self.coordinates for step in range(distance_till_end): # Check if there is a robot on the next coordinates. # Skip this if the shooting robot's current coordinates are checked if next_coordinates != self.coordinates: robot_in_the_way = state.check_robot_in_the_way(next_coordinates) # There is a robot, shoot him and break the cycle (only one gets shot). if robot_in_the_way: robot_in_the_way.be_damaged() break # Check if there is a wall, if is: end of shot. if not state.check_the_absence_of_a_wall(next_coordinates, self.direction): break # No robots or walls on the coordinates, check one step further. else: next_coordinates = get_next_coordinates(next_coordinates, self.direction)
def move(self, direction, distance, state): """ Move a robot to new coordinates according to direction of the move. When robot is moved by game elements (convoyer belt or pusher), he doesn't have enough power to push other robots. If there is a robot in the way, the movement is stopped. """ for step in range(distance): # Check walls before moving. if not check_wall(self.coordinates, direction, state): break # There is no wall. Get new coordinates. next_coordinates = get_next_coordinates(self.coordinates, direction) # Check robots on the next tile before moving. robot_check = True for robot in state.robots: if robot.coordinates == next_coordinates: # There is a robot on the next tile. # Robot can't be moved. robot_check = False break # There isn't a robot on the next tile. Robot will be moved. if robot_check: self.coordinates = next_coordinates # Check hole on new coordinates. self.check_hole(state)
def walk(self, distance, state, direction=None, push_others=True): """ Move a robot to next coordinates based on his direction. Optional argument: direction - Default value is set to robot's direction. When robot walks, he can move other robots in the way. """ if direction is None: direction = self.direction # Robot can go backwards - then his distance is -1. # In this case he walks 1 step in the direction opposite to the given one. # He can still move the other robots on the way. if distance < 0: self.walk((-distance), state, direction.get_new_direction(Rotation.U_TURN), push_others=push_others) else: for step in range(distance): # Check the absence of a walls before moving. if not check_the_absence_of_a_wall(self.coordinates, direction, state): break # There is no wall. Get next coordinates. next_coordinates = get_next_coordinates( self.coordinates, direction) # Check robots on the next tile before moving. robot_in_the_way = check_robot_in_the_way( state, next_coordinates) # Move robot in the way. if robot_in_the_way: if push_others: robot_in_the_way.walk(1, state, direction) # Check that robot moved. if robot_in_the_way.coordinates == next_coordinates: break else: break # Robot walks to next coordinates. self.coordinates = next_coordinates # Check hole on next coordinates. self.fall_into_hole(state) # If robot falls into hole, he becomes inactive. if self.inactive: break
def walk(self, distance, state, direction=None): """ Move a robot to new coordinates based on his direction. Optional argument: direction - Default value is set to robot's direction. When robot walks, he can move other robots in the way. """ if direction is None: direction = self.direction # Robot can go backwards - then his distance is -1. # In this case we want to rotate him, make him walk 1 step and rotate back. # He still can move the other robots on the way. if distance < 0: self.rotate(Rotation.U_TURN) self.walk((-distance), state) self.rotate(Rotation.U_TURN) for step in range(distance): # Check walls before moving. if not check_wall(self.coordinates, direction, state): break # There is no wall. Get new coordinates. next_coordinates = get_next_coordinates(self.coordinates, direction) # Check robots on the next tile. robot_in_the_way = None for robot in state.robots: if robot.coordinates == next_coordinates: # Save index of robot that is in the way. robot_in_the_way = state.robots.index(robot) break # Move robot in the way. if robot_in_the_way is not None: state.robots[robot_in_the_way].walk(1, state, direction) # Check that robot moved. if state.robots[ robot_in_the_way].coordinates != next_coordinates: # Robot walks to new coordinates. self.coordinates = next_coordinates # Check hole on new coordinates. self.check_hole(state) # There isn't a robot in the way. Robot walks to new coordinates. else: self.coordinates = next_coordinates # Check hole on new coordinates. self.check_hole(state)
def get_next_coordinates_for_belts(self, express_belts): """ Get all robot's next coordinates after move of certain type of conveyor belts. express_belts: a boolean, True - for express belts, False - for all belts. Return a dictionary of robots as keys and their next coordinates as values. """ robots_next_coordinates = {} for robot in self.get_active_robots(): for tile in self.get_tiles(robot.coordinates): if tile.check_belts(express_belts): # Get next coordinates of robots on belts robots_next_coordinates[robot] = get_next_coordinates( robot.coordinates, tile.direction.get_new_direction(tile.direction_out) ) break else: # Other robots will have the same coordinates robots_next_coordinates[robot] = robot.coordinates return robots_next_coordinates
def shoot_robot(self, robot, state): # Robot stands on laser tile. # If robot isn't standing on the start of the laser, look for other robots. if not self.start: # Get coordinates of current robot. (x, y) = robot.coordinates # Get coordinates of other robots. coordinates = [] for robot_state in state.robots: coordinates.append(robot_state.coordinates) # Get direction in which it will be checked for other robots or laser start. direction_to_start = self.direction.get_new_direction( Rotation.U_TURN) # Check if there is another robot in direction of incoming laser. while True: # Get new coordinates. (x, y) = get_next_coordinates((x, y), direction_to_start) # Check for other robots. if (x, y) in coordinates: # There is another robot. # Current robot won't be hit by laser. return # Get new tiles. new_tiles = state.get_tiles((x, y)) for tile in new_tiles: # Check if new tiles contain follow-up LaserTile in correct direction. if isinstance( tile, LaserTile) and tile.direction == self.direction: # Follow-up laser tile found, don't check ohter tiles here. break # Check for laser start tile. if tile.start: # Don't check new tiles. break robot.be_damaged(self.laser_strength)