Exemple #1
0
    def _djikstra(board, my_position, bombs, enemies, depth=None):
        def out_of_range(p1, p2):
            x1, y1 = p1
            x2, y2 = p2
            return depth is not None and abs(y2 - y1) + abs(x2 - x1) > depth

        items = defaultdict(list)
        dist = {}
        prev = {}
        Q = []

        for r in range(len(board)):
            for c in range(len(board[0])):
                position = (r, c)
                if not utility.position_is_fog(board, position):
                    dist[position] = np.inf
                    prev[position] = None
                    Q.append(position)

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

        while Q:
            Q = sorted(Q, key=lambda position: dist[position])

            position = Q.pop(0)
            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 not utility.position_on_board(
                            board, new_position) or utility.position_is_fog(
                                board, new_position):
                        continue
                    if out_of_range(my_position, new_position):
                        continue

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

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

        return items, dist, prev
Exemple #2
0
    def _djikstra(board, my_position, bombs, enemies):
        items = defaultdict(list)
        dist = {}
        prev = {}
        Q = []

        for r in range(len(board)):
            for c in range(len(board[0])):
                position = (r, c)
                if board[position] != utility.Item.Fog.value:
                    dist[position] = inf
                    prev[position] = None
                    Q.append(position)

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

        while Q:
            Q = sorted(Q, key=lambda position: dist[position])

            position = Q.pop(0)
            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 not utility.position_on_board(
                            board, new_position) or utility.position_is_fog(
                                board, new_position):
                        continue

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

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

        return items, dist, prev
Exemple #3
0
    def _find_safe_directions(self, board, my_position, unsafe_directions,
                              bombs, enemies):
        # 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] = utility.Item.Bomb.value

            for direction, bomb_range in unsafe_directions.items():
                next_position = utility.get_next_position(
                    my_position, direction)
                nx, ny = next_position
                if not utility.position_on_board(next_board, next_position) or \
                   not utility.position_is_passable(next_board, next_position, enemies):
                    continue

                is_stuck = True
                next_items, next_dist, next_prev = self._djikstra(
                    next_board, next_position, bombs, enemies, depth=10)
                for passage_position in next_items.get(utility.Item.Passage):
                    position_dist = next_dist[passage_position]
                    if position_dist == np.inf:
                        continue

                    if position_dist > bomb_range:
                        is_stuck = False
                        break

                    px, py = passage_position
                    if nx != px and ny != py:
                        is_stuck = False
                        break

                if not is_stuck:
                    safe.append(direction)
            if not safe:
                safe = [utility.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 [utility.Action.Stop]

        return safe