Exemple #1
0
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_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
Exemple #3
0
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
Exemple #4
0
 def neighbor_test(my_pos, life_value):
     x, y = my_pos
     i = x - 1
     sz = len(board)
     while i >= 0:
         position = (i, y)
         if not utility.position_on_board(board, position):
             break
         if int(bomb_life[i, y]) <= life_value and blast_st[i,
                                                            y] > abs(i - x):
             return False
         if not position_can_be_bomb_through(board, position):
             break
         i -= 1
     i = x + 1
     while i < sz:
         position = (i, y)
         if not utility.position_on_board(board, position):
             break
         if int(bomb_life[i, y]) <= life_value and blast_st[i,
                                                            y] > abs(i - x):
             return False
         if not position_can_be_bomb_through(board, position):
             break
         i += 1
     j = y - 1
     while j >= 0:
         position = (x, j)
         if not utility.position_on_board(board, position):
             break
         if int(bomb_life[x, j]) <= life_value and blast_st[x,
                                                            j] > abs(j - y):
             return False
         if not position_can_be_bomb_through(board, position):
             break
         j -= 1
     j = y + 1
     while j < sz:
         position = (x, j)
         if not utility.position_on_board(board, position):
             break
         if int(bomb_life[x, j]) <= life_value and blast_st[x,
                                                            j] > abs(j - y):
             return False
         if not position_can_be_bomb_through(board, position):
             break
         j += 1
     return True
Exemple #5
0
        def is_stuck_direction(next_position, bomb_range, next_board, enemies):
            Q = queue.PriorityQueue()
            Q.put((0, next_position))
            seen = set()

            nx, ny = next_position
            is_stuck = True
            while not Q.empty():
                dist, position = Q.get()
                seen.add(position)

                px, py = position
                if nx != px and ny != py:
                    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 + px, col + py)
                    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 + px - nx) + abs(col + py - ny)
                    Q.put((dist, new_position))
            return is_stuck
def is_valid_position(board, position, direction, step):
    row, col = position
    invalid_values = [item.value for item \
                                        in [constants.Item.Rigid]]
    if utility.position_on_board(board, position) == False:
        return False

    if constants.Action(direction) == constants.Action.Stop:
        return True

    if constants.Action(direction) == constants.Action.Up:
        return row - step >= 0 and board[row - step][col] not in invalid_values

    if constants.Action(direction) == constants.Action.Down:
        return row + step < len(board) and board[
            row + step][col] not in invalid_values

    if constants.Action(direction) == constants.Action.Left:
        return col - step >= 0 and board[row][col - step] not in invalid_values

    if constants.Action(direction) == constants.Action.Right:
        return col + step < len(board[0]) and \
            board[row][col+step] not in invalid_values

    raise constants.InvalidAction("We did not receive a valid direction: ",
                                  direction)
Exemple #7
0
def _compute_min_evade_step(obs, parent_pos_list, pos, bomb_real_life):
    flag_cover, min_cover_value, max_cover_value = _position_covered_by_bomb(obs, pos, bomb_real_life)
    if not flag_cover:
        return 0
    elif len(parent_pos_list) >= max_cover_value:
        if len(parent_pos_list) > max_cover_value + FLAME_LIFE:
            return 0
        else:
            return INT_MAX
    elif len(parent_pos_list) >= min_cover_value:
        if len(parent_pos_list) > min_cover_value + FLAME_LIFE:
            return 0
        else:
            return INT_MAX
    else:
        board = obs['board']
        dirs = _all_directions(exclude_stop=True)
        min_step = INT_MAX
        for d in dirs:
            next_pos = utility.get_next_position(pos, d)
            if not utility.position_on_board(board, next_pos):
                continue
            if not (utility.position_is_passage(board, next_pos) or \
                    utility.position_is_powerup(board, next_pos)):
                continue
            if next_pos in parent_pos_list:
                continue
            x = _compute_min_evade_step(obs, parent_pos_list + [next_pos], next_pos, bomb_real_life)
            min_step = min(min_step, x + 1)
        return min_step
Exemple #8
0
def _check_if_flame_will_gone(obs, prev_two_obs, flame_pos):
    assert (prev_two_obs[0] is not None)
    assert (prev_two_obs[1] is not None)
    # check the flame group in current obs, see if
    # the whole group was there prev two obs
    # otherwise, although this flame appears in prev two obs,
    # it could be a old overlap new, thus will not gone next step
    if not (utility.position_is_flames(prev_two_obs[0]['board'], flame_pos) \
            and utility.position_is_flames(prev_two_obs[1]['board'], flame_pos)):
        return False
    board = obs['board']
    Q = deque(maxlen=121)
    Q.append(flame_pos)
    visited = [flame_pos]
    dirs = _all_directions(exclude_stop=True)
    while len(Q) > 0:
        pos = Q.popleft()
        if not (utility.position_is_flames(prev_two_obs[0]['board'], pos) \
                and utility.position_is_flames(prev_two_obs[1]['board'], pos)):
            return False
        for d in dirs:
            next_pos = utility.get_next_position(pos, d)
            if utility.position_on_board(board, next_pos) and utility.position_is_agent(board, next_pos):
                if next_pos not in visited:
                    Q.append(next_pos)
                    visited.append(next_pos)
    return True
Exemple #9
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
Exemple #10
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 _filter_direction_toward_flames(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 not utility.position_is_flames(board, position):
            ret.append(direction)
    return ret
def get_next_step_flaming_positions(my_position, board, bomb_life,
                                    bomb_blast_st, enemies, teammate):
    def add_to_danger_positions(pos, danger_positions, board, blast_st,
                                bomb_life, covered_bomb_positions):
        '''due to bombing chain, bombs with life>=2 would still blow up if they are in the danger positions '''
        sz = int(blast_st[pos])
        x, y = pos
        danger_positions.add(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):
                    danger_positions.add(pos2)
                    if bomb_life[pos2] > 1:
                        covered_bomb_positions.add(pos2)

    blast_st = bomb_blast_st
    all_other_agents = [e.value for e in enemies] + [teammate.value]
    #direction_list = [constants.Action.Left, constants.Action.Up, constants.Action.Right, constants.Action.Down]
    going_to_explode_bomb_positions = list(zip(*np.where(bomb_life == 1)))
    may_be_kicked = []
    for pos in going_to_explode_bomb_positions:
        for direction in [
                constants.Action.Left, constants.Action.Up,
                constants.Action.Right, constants.Action.Down
        ]:
            pos2 = utility.get_next_position(pos, direction)
            if not utility.position_on_board(board, pos2):
                continue
            if board[pos2] in all_other_agents:
                #mark to kicked
                #may_be_kicked.append(pos)
                break
    surely_danger_bomb_positions = [
        pos for pos in going_to_explode_bomb_positions
        if pos not in may_be_kicked
    ]
    danger_positions = set()

    covered_bomb_positions = set()
    for pos in surely_danger_bomb_positions:
        add_to_danger_positions(pos, danger_positions, board, blast_st,
                                bomb_life, covered_bomb_positions)

    all_covered = set()
    while len(covered_bomb_positions) > 0:
        for pos in list(covered_bomb_positions):
            add_to_danger_positions(pos, danger_positions, board, blast_st,
                                    bomb_life, covered_bomb_positions)
            all_covered.add(pos)

        for pos in list(covered_bomb_positions):
            if pos in all_covered:
                covered_bomb_positions.remove(pos)

    #print('agent pos:', my_position, 'danger:', danger_positions)
    return danger_positions
 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
Exemple #14
0
def get_power_up(obs):
    res = [0] * 6
    my_position = obs['position']
    board = obs['board']
    for act in dirs:
        next_pos = util.get_next_position(my_position, act)
        if util.position_on_board(
                board, next_pos) and util.position_is_powerup(board, next_pos):
            res[act.value] = 1
    return res
Exemple #15
0
def dead_end(obs):
    res = [0] * 6
    pos = tuple(obs['position'])
    board = np.array(obs['board'])
    for direction in dirs:
        next_pos = util.get_next_position(pos, direction)
        if util.position_on_board(board, next_pos) and is_dead_end(
                board, pos, direction):
            res[direction.value] = -1
    return res
Exemple #16
0
 def is_moving_direction(bomb_pos, direction):
     rev_d = _opposite_direction(direction)
     rev_pos = utility.get_next_position(bomb_pos, rev_d)
     if not utility.position_on_board(prev_obs['board'], rev_pos):
         return False
     if prev_obs['bomb_life'][rev_pos] - 1 == obs['bomb_life'][bomb_pos] \
             and prev_obs['bomb_blast_strength'][rev_pos] == obs['bomb_blast_strength'][bomb_pos] \
             and utility.position_is_passage(prev_obs['board'], bomb_pos):
         return True
     return False
Exemple #17
0
def no_flames(obs):
    res = [0] * 6
    my_position = obs['position']
    board = obs['board']
    x, y = my_position
    for act in dirs:
        next_pos = util.get_next_position(my_position, act)
        if util.position_on_board(board, next_pos) and util.position_is_flames(
                board, next_pos):
            res[act.value] = -1
    return res
Exemple #18
0
def _stop_condition(board, pos, exclude_agent=True):
    if not utility.position_on_board(board, pos):
        return True
    if utility.position_is_fog(board, pos):
        return True
    if utility.position_is_wall(board, pos):
        return True
    if not exclude_agent:
        if utility.position_is_agent(board, pos):
            return True
    return False
Exemple #19
0
 def is_moving_direction(bomb_pos, direction):  # 炸弹是否在移动
     rev_d = _opposite_direction(direction)  # 返回 bomb 移动方向的反向
     rev_pos = utility.get_next_position(bomb_pos, rev_d)  # 上一帧 bomb 的位置
     if not utility.position_on_board(
             prev_obs['board'], rev_pos):  # 如果上一帧位置不在 board 上, 返回 False
         return False
     if prev_obs['bomb_life'][rev_pos] - 1 == obs['bomb_life'][bomb_pos] \
             and prev_obs['bomb_blast_strength'][rev_pos] == obs['bomb_blast_strength'][bomb_pos] \
             and utility.position_is_passage(prev_obs['board'], bomb_pos):
         return True  # 与上一帧是同一个bomb 并且当前位置是一个过道0 返回 True
     return False
def _filter_legal_actions(state):
    my_position = tuple(state['position'])
    board = np.array(state['board'])
    enemies = [constants.Item(e) for e in state['enemies']]
    ret = [constants.Action.Bomb]
    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 _opponent_test(board, candidate_position, enemies):
    assert (position_is_passable(board, candidate_position))
    #make sure this passage is not next to the opponent, otherwise the opponent may come to this position
    for direction in [
            constants.Action.Left, constants.Action.Up, constants.Action.Right,
            constants.Action.Down
    ]:
        position = utility.get_next_position(candidate_position, direction)
        if not utility.position_on_board(board, position):
            continue
        if utility.position_is_enemy(board, position, enemies):
            return False
    return True
 def add_to_danger_positions(pos, danger_positions, board, blast_st,
                             bomb_life, covered_bomb_positions):
     '''due to bombing chain, bombs with life>=2 would still blow up if they are in the danger positions '''
     sz = int(blast_st[pos])
     x, y = pos
     danger_positions.add(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):
                 danger_positions.add(pos2)
                 if bomb_life[pos2] > 1:
                     covered_bomb_positions.add(pos2)
def _position_will_be_flamed(board, position, bomb_life, bomb_blast_st,
                             directions_to_check):
    for direction in directions_to_check:
        pos = utility.get_next_position(position, direction)
        k = 1
        while utility.position_on_board(board, pos):
            if utility.position_is_wall(board, pos):
                break
            if bomb_life[pos] > 0 and bomb_blast_st[pos] - 1 >= k:
                return True
            pos = utility.get_next_position(pos, direction)
            k += 1
    return False
Exemple #24
0
 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
Exemple #25
0
def valid_directions(obs):
    res = [0] * 6
    pos = obs['position']
    board = obs['board']
    enemies = obs['enemies']
    for act in dirs:
        next_pos = util.get_next_position(pos, act)
        if util.position_on_board(board,
                                  next_pos) and util.position_is_passable(
                                      board, next_pos, enemies):
            res[act.value] = 1
        else:
            res[act.value] = -1
    return res
Exemple #26
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)
def _teammate_test(board, candidate_position, teammate,
                   next_step_flaming_positions):
    assert (position_is_passable(board, candidate_position))
    #make sure this passage is not next to your teammate if your teammate is in "danger" (thus teammate must come here to be safe)
    for direction in [
            constants.Action.Left, constants.Action.Up, constants.Action.Right,
            constants.Action.Down
    ]:
        position = utility.get_next_position(candidate_position, direction)
        if not utility.position_on_board(board, position):
            continue
        if board[
                position] == teammate and position in next_step_flaming_positions:
            return False
    return True
Exemple #28
0
    def get_score(self):
        score = 0
        # self_agent = self.self_agent
        self_agent_value = self.self_agent if type(
            self.self_agent) == int else self.self_agent.value
        #if the enemy agent is not alive, then the score increases
        for i, agent in enumerate(self.curr_agents):
            if 10 + i != self_agent_value:
                if not agent.is_alive:
                    score += 5
            else:
                #if we are dead, fk
                if not agent.is_alive:
                    score -= score * 0.95

        # if the agent is close to its enemy, then the score goes up
        self_agent_instance = self.curr_agents[self_agent_value - 10]
        for i, agent in enumerate(self.curr_agents):
            if 10 + i == self_agent_value:
                continue
            if not agent.is_alive:
                continue
            tar, tac = agent.position  # target agent row, target agent column
            sar, sac = self_agent_instance.position
            distance = abs(tar - sar) + abs(
                tac - sac)  #(((tar - sar) ** 2 + (tac - sac) ** 2) ** 0.5
            if distance != 0:
                score += (1 / distance * 5) * 5
        # if the agent has eaten good stuff, then score goes up
        if self._obs['position'] in self.last_items:
            val = self.last_items[self._obs['position']]
            # if val != constants.Item.Skull.value:
            score += 5
            # else:
            # score -= 5

        # if I placed bomb near wood, then score goes up
        for (k, v) in self.bombing_agents.items():
            if v is self_agent_value - 10 and self._bomb_life[k[0]][
                    k[1]] == 24:
                for p in [(k[0] - 1, k[1]), (k[0] + 1, k[1]), (k[0], k[1] - 1),
                          (k[0], k[1] + 1)]:
                    if utility.position_on_board(self._board, p) and \
                       self._board[p] == constants.Item.Wood.value:
                        score += 3
        return score
def _count_adjacent_walls(board, position, items, enemies):
    walls_count = 0
    not_passible_items = items[constants.Item.Wood] + items[
        constants.Item.Rigid] + items[constants.Item.Bomb] + items[
            constants.Item.Flames]

    for enemy in enemies:
        not_passible_items += items.get(enemy, [])

    for direction in [
            constants.Action.Up, constants.Action.Down, constants.Action.Left,
            constants.Action.Right
    ]:
        new_pos = utility.get_next_position(position, direction)

        if not utility.position_on_board(board, new_pos) or \
            new_pos in not_passible_items:
            walls_count = walls_count + 1

    return walls_count
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