Example #1
0
def _kick_test(board, blast_st, bomb_life, my_position, direction):
    def moving_bomb_check(moving_bomb_pos, p_dir, time_elapsed):
        pos2=utility.get_next_position(moving_bomb_pos, p_dir)
        dist=0
        for i in range(10):
            dist +=1
            if not utility.position_on_board(board, pos2):
                break
            if not (utility.position_is_powerup(board, pos2) or utility.position_is_passage(board, pos2)):
                break
            life_now=bomb_life[pos2] - time_elapsed
            if bomb_life[pos2]>0 and life_now>=-2 and life_now <= 0 and dist<blast_st[pos2]:
                return False
            pos2=utility.get_next_position(pos2, p_dir)
        return True
    next_position=utility.get_next_position(my_position, direction)
    assert(utility.position_in_items(board, next_position, [constants.Item.Bomb]))
    life_value=int(bomb_life[next_position])
    strength=int(blast_st[next_position])
    dist=0
    pos=utility.get_next_position(next_position, direction)
    perpendicular_dirs=[constants.Action.Left, constants.Action.Right] 
    if direction == constants.Action.Left or direction == constants.Action.Right:
        perpendicular_dirs=[constants.Action.Down, constants.Action.Up]
    for i in range(life_value): 
        if utility.position_on_board(board, pos) and utility.position_is_passage(board, pos):
            #do a check if this position happens to be in flame when the moving bomb arrives!
            if not (moving_bomb_check(pos, perpendicular_dirs[0], i) and moving_bomb_check(pos, perpendicular_dirs[1], i)):
                break
            dist +=1 
        else:
            break
        pos=utility.get_next_position(pos, direction)
        #can kick and kick direction is valid
    return dist > strength
    def _djikstra(board, my_position, bombs, enemies, depth=None, exclude=None):
        assert (depth is not None)

        if exclude is None:
            exclude = [
                constants.Item.Fog, constants.Item.Rigid, constants.Item.Flames
            ]

        def out_of_range(p_1, p_2):
            '''Determines if two points are out of rang of each other'''
            x_1, y_1 = p_1
            x_2, y_2 = p_2
            return abs(y_2 - y_1) + abs(x_2 - x_1) > depth

        items = defaultdict(list)
        dist = {}
        prev = {}
        Q = queue.PriorityQueue()

        my_x, my_y = my_position
        for r in range(max(0, my_x - depth), min(len(board), my_x + depth)):
            for c in range(max(0, my_y - depth), min(len(board), my_y + depth)):
                position = (r, c)
                if any([
                        out_of_range(my_position, position),
                        utility.position_in_items(board, position, exclude),
                ]):
                    continue

                if position == my_position:
                    dist[position] = 0
                else:
                    dist[position] = np.inf

                prev[position] = None
                Q.put((dist[position], position))

        for bomb in bombs:
            if bomb['position'] == my_position:
                items[constants.Item.Bomb].append(my_position)

        while not Q.empty():
            _, position = Q.get()

            if utility.position_is_passable(board, position, enemies):
                x, y = position
                val = dist[(x, y)] + 1
                for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                    new_position = (row + x, col + y)
                    if new_position not in dist:
                        continue

                    if val < dist[new_position]:
                        dist[new_position] = val
                        prev[new_position] = position

            item = constants.Item(board[position])
            items[item].append(position)

        return items, dist, prev
def position_has_no_escape(obs, flame_positions, consider_enemy=False):
    directions = [
        constants.Action.Left, constants.Action.Up, constants.Action.Right,
        constants.Action.Down
    ]
    my_position, can_kick, board, bomb_life, blast_st, enemies, teammate=obs['position'], \
    obs['can_kick'], obs['board'], obs['bomb_life'], obs['bomb_blast_strength'], obs['enemies'], obs['teammate']

    next_step_flaming_positions = get_next_step_flaming_positions(
        my_position, board, bomb_life, blast_st, enemies, teammate)
    future_flaming_positions = []
    for pos in list(zip(*np.where(bomb_life > 0))):
        sz = int(blast_st[pos])
        x, y = pos
        future_flaming_positions.append(pos)
        for i in range(1, sz):
            pos2_list = [(x + i, y), (x - i, y), (x, y + i), (x, y - i)]
            for pos2 in pos2_list:
                if utility.position_on_board(board, pos2):
                    future_flaming_positions.append(pos2)

    valid_directions = []
    num_passable = 0
    passable_position = None

    for direction in directions:
        next_pos = utility.get_next_position(my_position, direction)
        if not utility.position_on_board(board, next_pos):
            continue
        if can_kick and utility.position_in_items(board, next_pos,
                                                  [constants.Item.Bomb]):
            if kick_test(board, blast_st, bomb_life, my_position, direction):
                #passed kick test, so at least kick direction is an escape
                return False
            continue
        flag_passable = position_is_passable(board, next_pos, enemies)
        if not flag_passable:
            continue
        elif flag_passable and consider_enemy and next_pos in future_flaming_positions and passable_may_next_to_enemy(
                board, next_pos, enemies):
            continue
        else:
            num_passable += 1
            passable_position = next_pos
        if next_pos in flame_positions or next_pos in next_step_flaming_positions:
            continue
        valid_directions.append(direction)

    if num_passable == 0:
        return True
    if (my_position
            not in flame_positions) and (my_position
                                         not in next_step_flaming_positions):
        return False
    return len(valid_directions) == 0
Example #4
0
    def _fire_bomb(game_data, row, col, row_off, col_off, strength):
        if strength <= 0:
            return
        next_row = row + row_off
        next_col = col + col_off
        if not EnvSimulator._position_on_board(game_data, next_row, next_col):
            return
        if utility.position_in_items(
                game_data, (next_row, next_col),
            [constants.Item.Rigid, constants.Item.Wood]):
            return

        EnvSimulator._set_fire(game_data, next_row, next_col, False)

        EnvSimulator._fire_bomb(game_data, next_row, next_col, row_off,
                                col_off, strength - 1)
Example #5
0
    def _get_fire_positions_in_direction(board, x, y, strength, x_dir, y_dir,
                                         fire_pos):
        if strength <= 0 or not utility.position_on_board(board, (x, y)):
            return
        next_x = x + x_dir
        next_y = y + y_dir
        if not utility.position_on_board(board, (next_x, next_y)):
            return
        if utility.position_in_items(
                board, (next_x, next_y),
            [constants.Item.Rigid, constants.Item.Wood]):
            return

        fire_pos.append((next_x, next_y))
        EnvSimulator._get_fire_positions_in_direction(board, next_x, next_y,
                                                      strength - 1, x_dir,
                                                      y_dir, fire_pos)
def passable_may_next_to_enemy(board, position, enemies):
    #means enemy can get here in 2 steps thus block you!
    assert (position_is_passable(board, position, enemies))
    directions = [
        constants.Action.Left, constants.Action.Up, constants.Action.Right,
        constants.Action.Down
    ]
    for direction in directions:
        next_pos = utility.get_next_position(position, direction)
        if not utility.position_on_board(board, next_pos):
            continue
        if utility.position_in_items(board, next_pos, enemies):
            return True
        #if position_is_passable(board, next_pos):
        #    for d2 in directions:
        #        next_pos2=utility.get_next_position(next_pos, direction)
        #    if not utility.position_on_board(board, next_pos2):
        #        continue
        #    if utility.position_in_items(board, next_pos2, enemies):
        #        return True
    return False
Example #7
0
 def _get_items_in_direction(board, pos, strength, x_dir, y_dir, items):
     if strength <= 0 or not utility.position_on_board(board, pos):
         return
     x, y = pos
     next_x = x + x_dir
     next_y = y + y_dir
     if not utility.position_on_board(board, (next_x, next_y)):
         return
     item = board[(next_x, next_y)]
     try:
         if type(item) == tuple:
             print(item)
         if not item in items:
             items.append(item)
     except:
         if type(item) == tuple:
             print(item)
         print(item, items)
     if utility.position_in_items(
             board, (next_x, next_y),
         [constants.Item.Rigid, constants.Item.Wood]):
         return
     EnvSimulator._get_items_in_direction(board, (next_x, next_y),
                                          strength - 1, x_dir, y_dir, items)
Example #8
0
def _compute_safe_actions(obs, exclude_kicking=False, prev_two_obs=(None, None)):
    dirs = _all_directions(exclude_stop=True)
    ret = set()
    my_position, board, blast_st, bomb_life, can_kick = obs['position'], obs['board'], obs['bomb_blast_strength'], obs[
        'bomb_life'], obs['can_kick']
    kick_dir = None
    bomb_real_life_map = _all_bomb_real_life(board, bomb_life, blast_st)
    flag_cover_passages = []
    for direction in dirs:
        position = utility.get_next_position(my_position, direction)
        if not utility.position_on_board(board, position):
            continue
        if (not exclude_kicking) and utility.position_in_items(board, position, [constants.Item.Bomb]) and can_kick:
            # filter kick if kick is unsafe
            if _kick_test(board, blast_st, bomb_real_life_map, my_position, direction):
                ret.add(direction.value)
                kick_dir = direction.value
        gone_flame_pos = None
        if (prev_two_obs[0] != None and prev_two_obs[1] != None) and _check_if_flame_will_gone(obs, prev_two_obs,
                                                                                               position):
            # three consecutive flames means next step this position must be good
            # make this a candidate
            obs['board'][position] = constants.Item.Passage.value
            gone_flame_pos = position

        if utility.position_is_passage(board, position) or utility.position_is_powerup(board, position):
            my_id = obs['board'][my_position]
            obs['board'][my_position] = constants.Item.Bomb.value if bomb_life[
                                                                         my_position] > 0 else constants.Item.Passage.value
            flag_cover, min_cover_value, max_cover_value = _position_covered_by_bomb(obs, position, bomb_real_life_map)
            flag_cover_passages.append(flag_cover)
            if not flag_cover:
                ret.add(direction.value)
            else:
                min_escape_step = _compute_min_evade_step(obs, [position], position, bomb_real_life_map)
                assert (min_escape_step > 0)
                if min_escape_step < min_cover_value:
                    ret.add(direction.value)
            obs['board'][my_position] = my_id
        if gone_flame_pos is not None:
            obs['board'][gone_flame_pos] = constants.Item.Flames.value

    # Test Stop action only when agent is covered by bomb,
    # otherwise Stop is always an viable option
    my_id = obs['board'][my_position]
    obs['board'][my_position] = constants.Item.Bomb.value if bomb_life[
                                                                 my_position] > 0 else constants.Item.Passage.value
    # REMEMBER: before compute min evade step, modify board accordingly first..
    flag_cover, min_cover_value, max_cover_value = _position_covered_by_bomb(obs, my_position, bomb_real_life_map)
    if flag_cover:
        min_escape_step = _compute_min_evade_step(obs, [None, my_position], my_position, bomb_real_life_map)
        if min_escape_step < min_cover_value:
            ret.add(constants.Action.Stop.value)
    else:
        ret.add(constants.Action.Stop.value)
    obs['board'][my_position] = my_id
    # REMEBER: change the board back

    # Now test bomb action
    if not (obs['ammo'] <= 0 or obs['bomb_life'][obs['position']] > 0):
        # place bomb might be possible
        assert (BOMBING_TEST in ['simple', 'simple_adjacent', 'lookahead'])
        if BOMBING_TEST == 'simple':
            if not flag_cover:
                ret.add(constants.Action.Bomb.value)
        elif BOMBING_TEST == 'simple_adjacent':
            if (not flag_cover) and (not any(flag_cover_passages)):
                ret.add(constants.Action.Bomb.value)
        else:  # lookahead
            if (constants.Action.Stop.value in ret) and len(ret) > 1 and (kick_dir is None):
                obs2 = copy.deepcopy(obs)
                my_pos = obs2['position']
                obs2['board'][my_pos] = constants.Item.Bomb.value
                obs2['bomb_life'][my_pos] = min_cover_value if flag_cover else 10
                obs2['bomb_blast_strength'][my_pos] = obs2['blast_strength']
                bomb_life2, bomb_blast_st2, board2 = obs2['bomb_life'], obs2['bomb_blast_strength'], obs2['board']
                bomb_real_life_map = _all_bomb_real_life(board2, bomb_life2, bomb_blast_st2)
                min_evade_step = _compute_min_evade_step(obs2, [None, my_position], my_pos, bomb_real_life_map)
                current_cover_value = obs2['bomb_life'][my_pos]
                if min_evade_step < current_cover_value:
                    ret.add(constants.Action.Bomb.value)
    return ret
Example #9
0
def search_time_expanded_network(list_boards, my_position, id=None):
    """
    Find survivable time-positions in the list of boards from my position

    Parameters
    ----------
    list_boards : list
        list of boards, generated by _board_sequence
    my_position : tuple
        my position, where the search starts

    Return
    ------
    survivable : list
        list of the set of survivable time-positions at each time
        survivable[t] : set of survivable positions at time t
    prev : list
        prev[t] : dict
        prev[t][position] : list of positions from which
                                one can reach the position at time t
    succ : list
        succ[t] : dict
        succ[t][position] : list of positions to which
                                one can reach the position at time t + 1
    subtree : list
        subtree[t] : dict
        subtree[t][position] : set of time-positions that are the children of (t, position)
    """

    depth = len(list_boards)

    passable = [
        constants.Item.Passage, constants.Item.ExtraBomb,
        constants.Item.IncrRange, constants.Item.Kick
    ]

    if list_boards[0][my_position] == constants.Item.Flames.value:
        if id is None:
            return [set()] * depth
        else:
            return [set()] * depth, id

    # Forward search for reachable positions
    # reachable[(t,x,y]): whether can reach (x,y) at time t
    reachable = np.full((depth, ) + board_shape, False)
    reachable[(0, ) + my_position] = True
    next_positions = set([my_position])
    my_position_get_flame = False
    for t in range(1, depth):
        if list_boards[t][my_position] == constants.Item.Flames.value:
            my_position_get_flame = True
        curr_positions = next_positions

        _next_positions = list()
        # add all possible positions
        for curr_position in curr_positions:
            _next_positions.append(curr_position)
            x, y = curr_position
            for row, col in [(0, 0), (-1, 0), (1, 0), (0, -1), (0, 1)]:
                _next_positions.append((x + row, y + col))

        next_positions = list()
        for position in set(_next_positions):
            if not on_board(position[0], position[1]):
                # remove out of positions
                continue
            if any([
                    position == my_position and not my_position_get_flame,
                    utility.position_in_items(list_boards[t], position,
                                              passable)
            ]):
                next_positions.append(position)

        for position in next_positions:
            reachable[(t, ) + position] = True

    # Backward search for survivable positions
    # survivable[t]: set of survavable positions at time t
    survivable = [set() for _ in range(depth)]
    survivable[-1] = next_positions
    prev = [defaultdict(list) for _ in range(depth + 1)]
    for t in range(depth - 1, 0, -1):
        for position in survivable[t]:
            # for each position surviving at time t
            # if the position is on a bomb, I must have stayed there since I placed the bomb
            if list_boards[t][position] == constants.Item.Bomb.value:
                if reachable[(t - 1, ) + position]:
                    prev[t][position].append(position)
                    continue

            # otherwise, standard case
            x, y = position
            for row, col in [(0, 0), (-1, 0), (1, 0), (0, -1), (0, 1)]:
                # consider the prev_position at time t - 1
                prev_position = (x + row, y + col)
                if not on_board(prev_position[0], prev_position[1]):
                    # discard the prev_position if out of board
                    continue
                if reachable[(t - 1, ) + prev_position]:
                    # can reach the position at time t
                    # from the prev_position at time t-1
                    prev[t][position].append(prev_position)

        # the set of prev_positions at time t-1
        # from which one can reach the surviving positions at time t
        survivable[t - 1] = set(
            [position for prevs in prev[t].values() for position in prevs])

    if id is None:
        return survivable
    else:
        return survivable, id
Example #10
0
    def _djikstra(board,
                  my_position,
                  bombs,
                  enemies,
                  depth=None,
                  exclude=None):
        """
        Dijkstra method

        Parameters
        ----------
        board = np.array(obs['board'])

        my_position = tuple(obs['position'])

        bombs = convert_bombs(np.array(obs['bomb_blast_strength']))

        enemies = [constants.Item(e) for e in obs['enemies']]
        """

        if depth is None:
            depth = len(board) * 2

        if exclude is None:
            exclude = [
                constants.Item.Fog, constants.Item.Rigid, constants.Item.Flames
            ]

        def out_of_range(p1, p2):
            x1, y1 = p1
            x2, y2 = p2
            return abs(y2 - y1) + abs(x2 - x1) > depth

        items = defaultdict(list)

        for bomb in bombs:
            if bomb['position'] == my_position:
                items[constants.Item.Bomb].append(my_position)

        dist = {}
        prev = {}

        mx, my = my_position
        for r in range(max(0, mx - depth), min(len(board), mx + depth)):
            for c in range(max(0, my - depth), min(len(board), my + depth)):
                position = (r, c)
                if any([
                        out_of_range(my_position, position),
                        utility.position_in_items(board, position, exclude),
                ]):
                    continue

                if position == my_position:
                    dist[position] = 0
                else:
                    dist[position] = np.inf

                prev[position] = None

                item = constants.Item(board[position])
                items[item].append(position)

        # Djikstra
        H = []
        heapq.heappush(H, (0, my_position))
        while H:
            min_dist, position = heapq.heappop(H)

            if not utility.position_is_passable(board, position, enemies):
                continue

            x, y = position
            for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                new_position = (row + x, col + y)
                if new_position not in dist:
                    continue

                if min_dist + 1 < dist[new_position]:
                    dist[new_position] = min_dist + 1
                    prev[new_position] = position
                    heapq.heappush(H, (dist[new_position], new_position))

        return items, dist, prev
Example #11
0
    def _search_time_expanded_network(self, list_boards, my_position):

        """
        Find survivable time-positions in the list of boards from my position

        Parameters
        ----------
        list_boards : list
            list of boards, generated by _board_sequence
        my_position : tuple
            my position, where the search starts

        Return
        ------
        survivable : list
            list of the set of survivable time-positions at each time
            survivable[t] : set of survivable positions at time t
        prev : list
            prev[t] : dict
            prev[t][position] : list of positions from which
                                one can reach the position at time t
        """

        depth = len(list_boards)

        # TODO : what to do with Fog?
        exclude = [constants.Item.Fog,
                   constants.Item.Rigid,
                   constants.Item.Wood,
                   constants.Item.Bomb,
                   constants.Item.Flames,
                   constants.Item.AgentDummy]

        if list_boards[0][my_position] == constants.Item.Flames.value:
            return [set()] * depth, [list()] * depth
        
        # Forward search for reachable positions
        # reachable[(t,x,y]): whether can reach (x,y) at time t
        reachable = np.full((depth,) + self.board_shape, False)
        reachable[(0,)+my_position] = True
        next_positions = set([my_position])
        my_position_get_flame = False
        for t in range(1, depth):
            if list_boards[t][my_position] == constants.Item.Flames.value:
                my_position_get_flame = True
            curr_positions = next_positions
            next_positions = set()

            # add all possible positions
            for curr_position in curr_positions:
                next_positions.add(curr_position)
                x, y = curr_position
                for row, col in [(0, 0), (-1, 0), (1, 0), (0, -1), (0, 1)]:
                    next_positions.add((x + row, y + col))

            for position in next_positions.copy():
                if not self._on_board(position):
                    # remove out of positions
                    next_positions.remove(position)
                elif list_boards[t][position] == constants.Item.AgentDummy.value:
                    # TODO: this may be too conservative
                    # avoid contact to other agents
                    next_positions.remove(position)
                elif position == my_position and not my_position_get_flame:
                    # can stay even on bomb until getting flame
                    continue
                elif utility.position_in_items(list_boards[t], position, exclude):
                    # remove blocked
                    next_positions.remove(position)
                elif utility.position_is_agent(list_boards[t], position):
                    # if occupied by another agent
                    next_positions.remove(position)

            for position in next_positions:
                reachable[(t,)+position] = True

        # Backward search for survivable positions
        # survivable[t]: set of survavable positions at time t
        # prev[t][position]: list of positions from which
        #                    one can reach the position at time t
        survivable = [set() for _ in range(depth)]
        survivable[-1] = next_positions
        prev = [defaultdict(list) for _ in range(depth+1)]
        for t in range(depth-1, 0, -1):
            for position in survivable[t]:
                # for each position surviving at time t
                # if the position is on a bomb, I must have stayed there since I placed the bomb
                if list_boards[t][position] == constants.Item.Bomb.value:
                    if reachable[(t-1,)+position]:
                        prev[t][position].append(position)
                        continue

                # otherwise, standard case
                x, y = position
                for row, col in [(0, 0), (-1, 0), (1, 0), (0, -1), (0, 1)]:
                    # consider the prev_position at time t - 1
                    prev_position = (x + row, y + col)
                    if not self._on_board(prev_position):
                        # discard the prev_position if out of board
                        continue
                    if reachable[(t-1,)+prev_position]:
                        # can reach the position at time t
                        # from the prev_position at time t-1
                        prev[t][position].append(prev_position)

            # the set of prev_positions at time t-1
            # from which one can reach the surviving positions at time t
            survivable[t-1] = set([position for prevs in prev[t].values()
                                   for position in prevs])

        return survivable, prev
def get_filtered_directions(obs,
                            next_step_flaming_positions,
                            exclude_kicking=False):
    ret = set()
    my_position, board, blast_st, bomb_life, can_kick = obs['position'], obs[
        'board'], obs['bomb_blast_strength'], obs['bomb_life'], obs['can_kick']
    enemies = obs['enemies']
    teammate = obs['teammate'].value

    kick_dir = None
    could_be_occupied_dir = None
    for direction in [
            constants.Action.Left, constants.Action.Up, constants.Action.Right,
            constants.Action.Down
    ]:
        position = utility.get_next_position(my_position, direction)
        if not utility.position_on_board(board, position):
            continue
        if position in next_step_flaming_positions:
            continue

        if not exclude_kicking and utility.position_in_items(
                board, position, [constants.Item.Bomb]) and can_kick:
            #filter kick if kick is unsafe
            if kick_test(board, blast_st, bomb_life, my_position, direction):
                ret.add(direction.value)
                kick_dir = direction.value

        if position_is_passable(board, position, enemies):
            if bomb_life[my_position] > 0 and not agent_on_bomb_next_move_test(
                    my_position, direction, board, bomb_life, blast_st):
                #if moving to this passage leads to a long corridor
                continue

            if my_position in next_step_flaming_positions and not _opponent_test(
                    board, position, enemies):
                # if I am in danger, I should not go to a position which may also be the next position of enemies
                # unless this is the only passage
                could_be_occupied_dir = direction.value
                continue
            if not _teammate_test(board, position, teammate,
                                  next_step_flaming_positions):
                continue
            new_obs = step_to(obs, position)
            #one step lookahead search see if this new position would lead to no way dodge
            #if not is_going_into_siege(observ, old_pos, new_pos):
            flame_positions = next_step_flaming_positions
            # after step to the new_position, when check around, remember to
            # exclude those flame positions computed previously since they must have been filed with flames
            if not position_has_no_escape(
                    new_obs, flame_positions, consider_enemy=False):
                ret.add(direction.value)
    if len(ret) == 0 and could_be_occupied_dir is not None:
        ret.add(could_be_occupied_dir)
    if my_position not in next_step_flaming_positions and (
            not (kick_dir and len(ret) == 1)):
        new_obs = step_to(obs, my_position)
        if not (bomb_life[my_position] > 0 and
                bomb_life[my_position] <= 3) and not position_has_no_escape(
                    new_obs, next_step_flaming_positions, consider_enemy=True):
            ret.add(constants.Action.Stop.value)
    return ret
Example #13
0
    def _djikstra(board,
                  my_position,
                  bombs,
                  enemies,
                  bomb_timer=None,
                  depth=None,
                  exclude=None):

        if depth is None:
            depth = len(board) * 2

        if exclude is None:
            exclude = [
                constants.Item.Fog, constants.Item.Rigid, constants.Item.Flames
            ]

        def out_of_range(p1, p2):
            x1, y1 = p1
            x2, y2 = p2
            return abs(y2 - y1) + abs(x2 - x1) > depth

        items = defaultdict(list)

        for bomb in bombs:
            if bomb['position'] == my_position:
                items[constants.Item.Bomb].append(my_position)

        dist = {}
        prev = {}

        mx, my = my_position
        for r in range(max(0, mx - depth), min(len(board), mx + depth)):
            for c in range(max(0, my - depth), min(len(board), my + depth)):
                position = (r, c)
                if any([
                        out_of_range(my_position, position),
                        utility.position_in_items(board, position, exclude),
                ]):
                    continue

                if position == my_position:
                    dist[position] = 0
                else:
                    dist[position] = np.inf

                prev[position] = None

                item = constants.Item(board[position])
                items[item].append(position)

        # Djikstra
        H = []
        heapq.heappush(H, (0, my_position))
        while H:
            min_dist, position = heapq.heappop(H)

            if (board[position] != constants.Item.Bomb.value
                ) and not utility.position_is_passable(board, position,
                                                       enemies):
                continue

            x, y = position
            for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                new_position = (row + x, col + y)
                if new_position not in dist:
                    continue

                if not utility.position_is_passable(board, new_position,
                                                    enemies):
                    continue

                if bomb_timer is not None:
                    t = bomb_timer[new_position]
                    if t > 0 and abs((min_dist + 1) - t) < 2:
                        continue

                if min_dist + 1 < dist[new_position]:
                    dist[new_position] = min_dist + 1
                    prev[new_position] = position
                    heapq.heappush(H, (dist[new_position], new_position))

        return items, dist, prev
Example #14
0
def get_dijkstra_act(obs_nf, goal_abs, exclude=None, rang=11):
    # 放炸弹
    if goal_abs == rang * rang:
        return 5

    # 停止在原地
    my_position = tuple(obs_nf['position'])
    goal = extra_position(goal_abs, obs_nf)
    if goal == my_position:
        return 0

    board = np.array(obs_nf['board'])
    enemies = [constants.Item(e) for e in obs_nf['enemies']]

    if exclude is None:
        exclude = [
            constants.Item.Rigid,
            constants.Item.Wood,
        ]

    dist = {}
    prev = {}
    Q = queue.Queue()

    # my_x, my_y = my_position
    for r in range(0, rang):
        for c in range(0, rang):
            position = (r, c)

            if any([utility.position_in_items(board, position, exclude)]):
                continue

            prev[position] = None

            if position == my_position:
                Q.put(position)
                dist[position] = 0
            else:
                dist[position] = np.inf

    while not Q.empty():
        position = Q.get()

        if position_is_passable(board, position, enemies):
            x, y = position
            val = dist[(x, y)] + 1
            for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                new_position = (row + x, col + y)
                if new_position not in dist:
                    continue

                if val < dist[new_position]:
                    dist[new_position] = val
                    prev[new_position] = position
                    Q.put(new_position)
                elif val == dist[new_position] and random.random() < .5:
                    dist[new_position] = val
                    prev[new_position] = position

    row_g, col_g = goal
    my_x, my_y = my_position
    up = (-1, 0)
    down = (1, 0)
    left = (0, -1)
    right = (0, 1)
    # 判断goal是否可以达到
    while goal in dist and prev[goal] != my_position:
        goal = prev[goal]

    legal_act = []
    # 无法到达有效目的
    if goal not in dist:
        # 可以向下行走
        if row_g > my_x:
            if isLegal_act(obs_nf, down, rang=rang): legal_act.append(2)
        elif row_g < my_x:
            if isLegal_act(obs_nf, up, rang=rang): legal_act.append(1)
        # 可以向右行走
        if col_g > my_x:
            if isLegal_act(obs_nf, right, rang=rang): legal_act.append(4)
        elif col_g < my_x:
            if isLegal_act(obs_nf, left, rang=rang): legal_act.append(3)
        if legal_act:
            return random.choice(legal_act)
    # 可以达到的目的
    else:
        count = 1
        for act_to in [up, down, left, right]:
            row, col = act_to
            if goal == (my_x + row, my_y + col):
                return count
            count += 1
    return 0
Example #15
0
def _djikstra_act_v1(obs_nf, goal_abs, exclude=None):
    if goal_abs == 121:
        return 5

    board = np.array(obs_nf['board'])
    my_position = tuple(obs_nf['position'])
    enemies = [constants.Item(e) for e in obs_nf['enemies']]

    if exclude is None:
        exclude = [
            constants.Item.Rigid,
            constants.Item.Wood,
        ]

    dist = {}
    prev = {}
    Q = queue.Queue()

    # my_x, my_y = my_position
    for r in range(0, 11):
        for c in range(0, 11):
            position = (r, c)

            if any([utility.position_in_items(board, position, exclude)]):
                continue

            prev[position] = None

            if position == my_position:
                Q.put(position)
                dist[position] = 0
            else:
                dist[position] = np.inf

    while not Q.empty():
        position = Q.get()

        if position_is_passable(board, position, enemies):
            x, y = position
            val = dist[(x, y)] + 1
            for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                new_position = (row + x, col + y)
                if new_position not in dist:
                    continue

                if val < dist[new_position]:
                    dist[new_position] = val
                    prev[new_position] = position
                    Q.put(new_position)
                elif val == dist[new_position] and random.random() < .5:
                    dist[new_position] = val
                    prev[new_position] = position

    goal = extra_goal(goal_abs)
    while goal in dist and prev[goal] != my_position:
        goal = prev[goal]

    # up, down, left, right
    my_x, my_y = my_position
    count = 1
    for act_abs in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
        row, col = act_abs
        if goal == (my_x + row, my_y + col):
            return count
        count += 1
    return 0
Example #16
0
def _djikstra_act_v4(obs_nf, goal_abs, exclude=None, rang=11):
    # 放炸弹
    if goal_abs == rang * rang:
        print_info('释放炸弹')
        return 5

    # 停止在原地
    my_position = tuple(obs_nf['position'])
    goal = extra_goal(goal_abs, rang=rang)
    # print('goal', goal)
    if goal == my_position:
        print_info('停在原地')
        return 0

    board = np.array(obs_nf['board'])
    enemies = [constants.Item(e) for e in obs_nf['enemies']]

    if exclude is None:
        exclude = [
            constants.Item.Rigid,
            constants.Item.Wood,
        ]

    dist = {}
    prev = {}
    Q = queue.Queue()

    # my_x, my_y = my_position
    for r in range(0, rang):
        for c in range(0, rang):
            position = (r, c)

            if any([utility.position_in_items(board, position, exclude)]):
                continue

            prev[position] = None

            if position == my_position:
                Q.put(position)
                dist[position] = 0
            else:
                dist[position] = np.inf

    while not Q.empty():
        position = Q.get()

        if position_is_passable(board, position, enemies):
            x, y = position
            val = dist[(x, y)] + 1
            for row, col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                new_position = (row + x, col + y)
                if new_position not in dist:
                    continue

                if val < dist[new_position]:
                    dist[new_position] = val
                    prev[new_position] = position
                    Q.put(new_position)
                elif val == dist[new_position] and random.random() < .5:
                    dist[new_position] = val
                    prev[new_position] = position

    row_g, col_g = goal
    my_x, my_y = my_position
    up = (-1, 0)
    down = (1, 0)
    left = (0, -1)
    right = (0, 1)
    # 判断goal是否可以达到
    while goal in dist and prev[goal] != my_position:
        goal = prev[goal]

    legal_act = []
    # 无法到达有效目的
    if goal not in dist:
        # print('random')
        goal_abs = random.randint(0, rang * rang)
        return _djikstra_act_v4(obs_nf, goal_abs, rang=rang)
    # 可以达到的目的
    else:
        count = 1
        for act_to in [up, down, left, right]:
            row, col = act_to
            if goal == (my_x + row, my_y + col):
                print_info('向目的地移动')
                return count
            count += 1
    print_info('非法的移动动作')
    return 0