def me_to_enemy_all_corridor(board, pos1, pos2): assert(pos1[0]==pos2[0] or pos1[1]==pos2[1]) if pos1[0]==pos2[0]: if pos1[1]<pos2[1]: direction=constants.Action.Right else: direction=constants.Action.Left else: if pos1[0]<pos2[0]: direction=constants.Action.Down else: direction=constants.Action.Up p_dirs=perpendicular_directions(direction) pos2_next=utility.get_next_position(pos2, direction) next_is_impasse=(not utility.position_on_board(board, pos2_next)) or utility.position_is_wall(board, pos2_next) if utility.position_on_board(board, pos2_next) and utility.position_is_fog(board, pos2_next): next_is_impasse=False if not (position_is_in_corridor(board, pos2, p_dirs) and next_is_impasse): # pos2:enempy must be in impasse return False all_corridor_flag=True pos=utility.get_next_position(pos1, direction) while pos!=pos2: if not (utility.position_is_passage(board, pos)): all_corridor_flag=False break if not position_is_in_corridor(board, pos, p_dirs): all_corridor_flag=False break pos=utility.get_next_position(pos, direction) return all_corridor_flag
def position_is_in_corridor(board, position, perpendicular_dirs): d1=perpendicular_dirs[0] d2=perpendicular_dirs[1] p1=utility.get_next_position(position, d1) p2=utility.get_next_position(position, d2) con1 = ( (not utility.position_on_board(board, p1)) or utility.position_is_wall(board, p1) ) con2 = ( (not utility.position_on_board(board, p2)) or utility.position_is_wall(board, p2) ) return con1 and con2
def _filter_invalid_directions(board, my_position, directions, enemies): ret = [] for direction in directions: position = utility.get_next_position(my_position, direction) if utility.position_on_board( board, position) and utility.position_is_passable( board, position, enemies): ret.append(direction) return ret
def _filter_recently_visited(directions, my_position, recently_visited_positions): ret = [] for direction in directions: if not utility.get_next_position( my_position, direction) in recently_visited_positions: ret.append(direction) if not ret: ret = directions return ret
def _filter_unsafe_directions(board, my_position, directions, bombs): ret = [] for direction in directions: x, y = utility.get_next_position(my_position, direction) is_bad = False for bomb in bombs: bomb_x, bomb_y = bomb['position'] blast_strength = bomb['blast_strength'] if (x == bomb_x and abs(bomb_y - y) <= blast_strength) or \ (y == bomb_y and abs(bomb_x - x) <= blast_strength): is_bad = True break if not is_bad: ret.append(direction) return ret
def _find_safe_directions(self, board, my_position, unsafe_directions, bombs, enemies): def is_stuck_direction(next_position, bomb_range, next_board, enemies): '''Helper function to do determine if the agents next move is possible.''' Q = queue.PriorityQueue() Q.put((0, next_position)) seen = set() next_x, next_y = next_position is_stuck = True while not Q.empty(): dist, position = Q.get() seen.add(position) position_x, position_y = position if next_x != position_x and next_y != position_y: is_stuck = False break if dist > bomb_range: is_stuck = False break for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]: new_position = (row + position_x, col + position_y) if new_position in seen: continue if not utility.position_on_board(next_board, new_position): continue if not utility.position_is_passable(next_board, new_position, enemies): continue dist = abs(row + position_x - next_x) + abs(col + position_y - next_y) Q.put((dist, new_position)) return is_stuck # All directions are unsafe. Return a position that won't leave us locked. safe = [] if len(unsafe_directions) == 4: next_board = board.copy() next_board[my_position] = constants.Item.Bomb.value for direction, bomb_range in unsafe_directions.items(): next_position = utility.get_next_position( my_position, direction) next_x, next_y = next_position if not utility.position_on_board(next_board, next_position) or \ not utility.position_is_passable(next_board, next_position, enemies): continue if not is_stuck_direction(next_position, bomb_range, next_board, enemies): # We found a direction that works. The .items provided # a small bit of randomness. So let's go with this one. return [direction] if not safe: safe = [constants.Action.Stop] return safe x, y = my_position disallowed = [] # The directions that will go off the board. for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]: position = (x + row, y + col) direction = utility.get_direction(my_position, position) # Don't include any direction that will go off of the board. if not utility.position_on_board(board, position): disallowed.append(direction) continue # Don't include any direction that we know is unsafe. if direction in unsafe_directions: continue if utility.position_is_passable(board, position, enemies) or utility.position_is_fog( board, position): safe.append(direction) if not safe: # We don't have any safe directions, so return something that is allowed. safe = [k for k in unsafe_directions if k not in disallowed] if not safe: # We don't have ANY directions. So return the stop choice. return [constants.Action.Stop] return safe