示例#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
示例#2
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
示例#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
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
示例#5
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
示例#6
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
示例#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
示例#8
0
def _position_covered_by_bomb(obs, pos, bomb_real_life_map):
    # return a tuple (True/False, min_bomb_life_value, max life value)
    min_bomb_pos, max_bomb_pos = None, None
    min_bomb_value, max_bomb_value = INT_MAX, -INT_MAX
    if obs['bomb_life'][pos] > 0:
        min_bomb_value, max_bomb_value = bomb_real_life_map[pos], bomb_real_life_map[pos]
        min_bomb_pos, max_bomb_pos = pos, pos
    dirs = _all_directions(exclude_stop=True)
    board = obs['board']
    for d in dirs:
        next_pos = pos
        while True:
            next_pos = utility.get_next_position(next_pos, d)
            if _stop_condition(board, next_pos, exclude_agent=True):
                # here should assume agents are dynamic
                break
            if obs['bomb_life'][next_pos] > 0 and obs['bomb_blast_strength'][next_pos] - 1 >= _manhattan_distance(pos,
                                                                                                                  next_pos):
                if bomb_real_life_map[next_pos] < min_bomb_value:
                    min_bomb_value = bomb_real_life_map[next_pos]
                    min_bomb_pos = next_pos
                if bomb_real_life_map[next_pos] > max_bomb_value:
                    max_bomb_value = bomb_real_life_map[next_pos]
                    max_bomb_pos = next_pos
                break
    if min_bomb_pos is not None:
        return True, min_bomb_value, max_bomb_value
    return False, INT_MAX, -INT_MAX
示例#9
0
def check_if_in_bomb_range(board, bombs, position):
    for b in bombs:
        #Set the direction to trace
        direction = None
        if (b['position'][0] == position[0] and
                abs(b['position'][1] - position[1]) <= b['blast_strength']):
            if b['position'][1] < position[1]:
                direction = constants.Action.Right
            elif b['position'][1] > position[1]:
                direction = constants.Action.Left
        elif (b['position'][1] == position[1]
              and abs(b['position'][0] - position[0]) <= b['blast_strength']):
            if b['position'][0] < position[0]:
                direction = constants.Action.Down
            elif b['position'][0] > position[0]:
                direction = constants.Action.Up
        else:
            continue

        if direction is None:
            return True

        #Trace from bomb to see if there's block in the way
        new_pos = b['position']
        while new_pos != position:
            new_pos = utility.get_next_position(new_pos, direction)
            if board[new_pos] in [
                    constants.Item.Rigid.value, constants.Item.Wood.value
            ]:
                break
        if new_pos == position:
            return True
    return False
示例#10
0
def is_dead_end(board, position, direction):
    npos = util.get_next_position(position, direction)
    counter = 0
    for d in dirs:
        if not util.is_valid_direction(board, npos, d):
            counter += 1
    return counter >= 3
示例#11
0
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 _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 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
示例#14
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
示例#15
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
示例#16
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
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
示例#18
0
文件: prune.py 项目: tu2id4n/my_pmm
 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
示例#19
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
    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
示例#21
0
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
示例#23
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
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
 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
示例#26
0
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
示例#28
0
 def get_bomb_real_life(bomb_position, bomb_real_life):
     """One bomb's real life is the minimum life of its adjacent bomb.
        Not that this could be chained, so please call it on each bomb mulitple times until
        converge
     """
     dirs = _all_directions(exclude_stop=True)
     min_life = bomb_real_life[bomb_position]
     for d in dirs:
         pos = bomb_position
         last_pos = bomb_position
         while True:
             pos = utility.get_next_position(pos, d)
             if _stop_condition(board, pos):
                 break
             if bomb_real_life[pos] > 0:
                 if bomb_real_life[pos] < min_life and \
                         _manhattan_distance(pos, last_pos) <= bomb_blast_st[pos] - 1:
                     min_life = bomb_real_life[pos]
                     last_pos = pos
                 else:
                     break
     return min_life
def agent_on_bomb_next_move_test(my_position, direction, board, bomb_life,
                                 blast_st):
    assert (bomb_life[my_position] > 0)
    st = min(int(bomb_life[my_position]), int(blast_st[my_position]))
    pos = my_position
    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]

    corrdior_pos = [True]
    for i in range(st):
        next_pos = utility.get_next_position(pos, direction)
        if not utility.position_on_board(board, next_pos):
            break
        if not position_is_passable(board, next_pos):
            break
        if is_in_corridor(board, next_pos, perpendicular_dirs):
            corrdior_pos.append(True)
        else:
            corrdior_pos.append(False)
        pos = next_pos
    return not all(corrdior_pos)
示例#30
0
文件: prune.py 项目: tu2id4n/my_pmm
def move_moving_bombs_to_next_position(prev_obs, obs):
    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

    bombs = zip(*np.where(obs['bomb_life'] > 1))
    moving_bombs = []
    for bomb_pos in bombs:
        moving_dir = None
        for d in [constants.Action.Left, constants.Action.Right, \
                  constants.Action.Up, constants.Action.Down]:
            if is_moving_direction(bomb_pos, d):
                moving_dir = d
                break
        if moving_dir is not None:
            moving_bombs.append((bomb_pos, moving_dir))
    board = obs['board']
    bomb_life = obs['bomb_life']
    bomb_blast_strength = obs['bomb_blast_strength']
    for bomb_pos, moving_dir in moving_bombs:
        next_pos = utility.get_next_position(bomb_pos, moving_dir)
        if not utility.position_on_board(obs['board'], next_pos):
            continue
        if utility.position_is_passage(obs['board'], next_pos):
            board[next_pos] = board[bomb_pos]
            bomb_life[next_pos] = bomb_life[bomb_pos]
            bomb_blast_strength[next_pos] = bomb_blast_strength[bomb_pos]
            board[bomb_pos] = constants.Item.Passage.value
            bomb_life[bomb_pos] = 0
            bomb_blast_strength[bomb_pos] = 0
    return obs