def resolve_halite_move(game, collision):
    """

    :param collision [0:ship1 1:ship2 2:move 3:dest1 4:res_func]
    :returns Returns the 'o' or the lateral move based on the one with the most halite. 'o' gets
        a 10% preference.
    """

    ship = collision[0]
    move = collision[2]
    position = collision[3]

    if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Resolving density move".format(ship.id))

    move_offsets = Direction.laterals(DIRECTIONS[move])
    move_offsets.append(Direction.Still)
    move_offsets.append(Direction.invert(DIRECTIONS[move]))

    best_moves = []
    for o in move_offsets:
        pos = ship.position.directional_offset(o)
        cell = game.game_map[pos]

        if o == Direction.Still:
            val = cell.halite_amount * 1.1
        elif o == Direction.invert(DIRECTIONS[move]):
            val = cell.halite_amount * .5
        else:
            val = cell.halite_amount

        best_moves.append((cell, val, o))

    best_moves.sort(key=lambda item: item[1], reverse=True)

    new_offset = None
    new_cell = None

    # try the cells to the left/right of the direction orginally attempted in order of
    # desirability. Additionally check staying still.
    for m in best_moves:
        if not m[0].is_occupied:
            new_offset = m[2]
            new_cell = m[0]
            break;

    # if no cell available, we know ship lost it's original cell, and the two lateral moves are
    # blocked, try the only remaining option, the inverse of the original, otherwise rewind
    if new_offset is None:
        cnt = unwind(game, ship)
        if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Resolve failed, Unwinding {} ships and using 'o'".format(ship.id, cnt))
        #game_map[ship].mark_unsafe(ship) # unwind will mark the cell unsafe
        move = 'o'
    else:
        if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Resolved by best cell {}".format(ship.id, new_cell.position))
        new_cell.mark_unsafe(ship)
        move = Direction.convert(new_offset)

    if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Successfully resolved density move collision. Move: {}".format(ship.id, move))

    return move
Beispiel #2
0
def resolve_nav_move(game, collision):
    """
    Resolve a nav move.

    Note: The current position of the ship is 'given up'/marked safe for others in get_move(),
    there is no guarantee the ship can remain in it's current position - be sure to check is_occupied
    for the current cell if returning 'o'

    :param game
    :param collision Collision tuple: (0:ship1 1:ship2 2:move 3:dest1 4:res_func)
    :returns Returns move based on a number of special cases, if none of these exists,
        returns a random move excluding the original collision move. Returns 'o' if no
        move exists.
    """

    ship1 = collision[0]
    ship2 = collision[1]
    move = collision[2]
    position = collision[3]

    collision_cell = game.game_map[position]
    ship_cell = game.game_map[ship1]

    if DEBUG & (DEBUG_NAV):
        logging.info("Nav - ship {} - Resolving nav move".format(ship1.id))

    if DEBUG & (DEBUG_NAV):
        logging.info(
            "Nav - Ship {} collided with ship {} at {} while moving {}".format(
                ship1.id, ship2.id, position, move))

    #base = get_base_positions(game, ship1.position)

    # don't let enemy ships on a dropoff/shipyard block arrivals or spawns. Halite from both ships will be deposited
    if collision_cell.structure_type is Shipyard and collision_cell.ship.owner != game.me.id:
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} collided with enemy ship {} at shipyard. Crashing"
                .format(ship1.id, ship2.id))
        collision_cell.mark_unsafe(ship1)
        ship1.path.pop()
        new_move = move

    elif ship2.position == collision_cell.position and ship2.owner != game.me.id and collision_cell.position in get_base_surrounding_cardinals(
            game, ship1.position):
        game.base_clear_request.insert(0, {
            "position": collision_cell.position,
            "ship": ship2
        })  # , "base": base

        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} sent a dropoff clear request for {}. Blocked by {}"
                .format(ship1.id, collision_cell.position, ship2.id))

        if game.game_map[ship1].is_occupied:
            new_move = None  # None == unwind
        else:
            ship_cell.mark_unsafe(ship1)
            new_move = "o"

    # when arriving at a droppoff, wait from entry rather than making a move
    # this probably will not work as well without entry/exit lanes
    elif ship1.path and ship1.path[
            0] == game.me.shipyard.position and game.game_map.calculate_distance(
                ship1.position, game.me.shipyard.position) <= 2:
        if game.game_map[ship1].is_occupied:
            new_move = None  # None == unwind
        else:
            ship_cell.mark_unsafe(ship1)
            new_move = "o"

    # when departing ...
    elif ship1.position == game.me.shipyard.position:
        # wait zero for enemy
        if collision_cell.ship.owner != game.me.id:
            collision_cell.mark_unsafe(ship1)
            ship1.path.pop()
            new_move = move
        # wait to leave for friendly, ... but make sure our old cell is available. prob should never happen
        # since we don't spawn with a ship already in shipyard, but rapid departure could cause this
        elif game.game_map[ship1].is_occupied:
            new_move = None  # None == unwind
        else:
            ship_cell.mark_unsafe(ship1)
            new_move = 'o'
    else:
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - ship {} collision at {} with ship {}. Resolving to random move {}"
                .format(ship1.id, position, ship2.id, move))
        new_move = resolve_random_move(game, collision, {
            "moves": [Direction.convert(m) for m in Direction.laterals(move)]
        })

        # popping the path point will allow nav around the blocking ship, buy this can
        # cause conjestion/screw up arrival/departure lanes if close to the dropoff
        if game.game_map.calculate_distance(ship2.position,
                                            game.me.shipyard.position) > 4:
            if len(ship1.path) > 1:
                ship1.path.pop()

    #
    # if we were not able to resolve above, unwind ...
    #
    if new_move is None:
        cnt = unwind(game, ship1)
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - ship {} - Resolved by unwinding {} ships".format(
                    ship1.id, cnt))
        #ship_cell.mark_unsafe(ship1) this is handled by unwind
        new_move = 'o'

    if DEBUG & (DEBUG_NAV):
        logging.info(
            "Nav - ship {} - Successfully resolved nav move collision. Move: {}"
            .format(ship1.id, new_move))

    return new_move
Beispiel #3
0
def get_nav_move(game,
                 ship,
                 waypoint_algorithm="astar",
                 args={"move_cost": "turns"}):
    game_map = game.game_map

    if DEBUG & (DEBUG_NAV):
        logging.info("NAV - ship {} getting nav move for path {}".format(
            ship.id, ship.path))

    if not check_fuel_cost(game, ship):
        return 'o'

    if len(ship.path) == 0:
        if DEBUG & (DEBUG_NAV):
            logging.info("NAV - ship {} empty path".format(ship.id))
        return 'o'

    next_position = ship.path[len(ship.path) - 1]

    # check to see if we have a waypoint, not a continous path
    if game_map.calculate_distance(ship.position, next_position) > 1:
        normalized_next_position = game_map.normalize(next_position)

        if DEBUG & (DEBUG_NAV):
            logging.info(
                "NAV - ship {} found waypoint {}, calulating complete path".
                format(ship.id, next_position))

        # calc a continous path
        path, cost = game_map.navigate(ship.position, normalized_next_position,
                                       waypoint_algorithm, args)

        if path is None:
            if DEBUG & (DEBUG_NAV):
                logging.info("NAV - ship {} Nav failed, can't reach {}".format(
                    ship.id, normalized_next_position))
            return 'o'
        else:
            if DEBUG & (DEBUG_NAV):
                logging.info(
                    "NAV - ship {} path to waypoint found with a cost of {} ({} turns)"
                    .format(ship.id, round(cost), len(path)))
            ship.path.pop()
            ship.path = ship.path + path

    new_position = ship.path[len(ship.path) - 1]
    if DEBUG & (DEBUG_NAV):
        logging.info("NAV - ship {} new_position: {}".format(
            ship.id, new_position))

    normalized_new_position = game_map.normalize(new_position)
    if DEBUG & (DEBUG_NAV):
        logging.info("NAV - ship {} normalized_new_position: {}".format(
            ship.id, normalized_new_position))

    # why?
    if normalized_new_position == ship.position:
        ship.path.pop()
        return 'o'

    cell = game_map[normalized_new_position]

    # use get_unsafe_moves() to get a normalized directional offset. We should always get one soln.
    offset = game_map.get_unsafe_moves(ship.position,
                                       normalized_new_position)[0]
    move = Direction.convert(offset)

    if DEBUG & (DEBUG_NAV):
        logging.info("NAV - Ship {} has potential move: {}".format(
            ship.id, move))

    # once we have the move, handle collisions
    if cell.is_occupied:
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} has a collision at {} while moving {}".format(
                    ship.id, normalized_new_position, move))
        # don't let enemy ships block the dropoff
        if cell.structure_type is Shipyard and cell.ship.owner != game.me.id:
            cell.mark_unsafe(ship)
            ship.path.pop()
        # when arriving at a droppoff, wait from entry rather than making a random
# this probably will not work as well if not using entry/exit lanes
        elif normalized_new_position == game.me.shipyard.position:
            move = "o"
        # when departing a shipyard, try not to head the wrong direction
        elif ship.position == game.me.shipyard.position:
            alternate_moves = Direction.laterals(move)
            move = "o"
            for alternate_move_offset in alternate_moves:
                alternate_pos = ship.position.directional_offset(
                    alternate_move_offset)
                alternate_cell = game_map[alternate_pos]
                if not alternate_cell.is_occupied:
                    alternate_cell.mark_unsafe(ship)
                    move = Direction.convert(alternate_move_offset)
        else:
            move = get_random_move(game, ship)
            if move == "o":
                if DEBUG & (DEBUG_NAV):
                    logging.info(
                        "NAV - ship {} collision at {} with ship {}, using {}".
                        format(ship.id, normalized_new_position, cell.ship.id,
                               move))
    else:
        cell.mark_unsafe(ship)
        ship.path.pop()

    return move
Beispiel #4
0
def get_density_move(game, ship):

    move = "o"

    if DEBUG & (DEBUG_NAV):
        logging.info("Nav - ship {} is getting a density based move".format(
            ship.id))

    if not check_fuel_cost(game, ship):
        return move

    moves = []
    for quadrant in get_surrounding_cell_blocks(game, ship, 3, 3):
        directional_offset = quadrant[0]
        block = quadrant[1]

        if block.get_max() > constants.MAX_HALITE * MINING_THRESHOLD_MULT:
            moves.append((directional_offset, block, block.get_mean()))

    sorted_blocks = sorted(moves, key=lambda item: item[2], reverse=True)

    if len(sorted_blocks) == 0:
        return get_random_move(
            game, ship
        )  # FIX ME FIX ME FIX ME FIX ME FIX ME FIX ME would be better to try a large search radius ???

    best_bloc_data = sorted_blocks[0]

    max_cell = best_bloc_data[1].get_max()

    bc = best_bloc_data[1].get_cells()

    for best_cell in bc:
        if best_cell.halite_amount == max_cell:
            break

    move_offset = best_bloc_data[0]
    if DEBUG & (DEBUG_NAV):
        logging.info("Nav - Ship {} moveOffset: {}".format(
            ship.id, move_offset))

    new_position = game.game_map.normalize(
        ship.position.directional_offset(move_offset))
    if DEBUG & (DEBUG_NAV):
        logging.info("Nav - Ship {} new_position: {}".format(
            ship.id, new_position))

    normalized_position = game.game_map.normalize(new_position)
    if DEBUG & (DEBUG_NAV):
        logging.info("Nav - Ship {} normalized_position: {}".format(
            ship.id, normalized_position))

    cell = game.game_map[normalized_position]

    if not cell.is_occupied:
        move = Direction.convert(move_offset)
        cell.mark_unsafe(ship)
        #game.game_map[ship.position].mark_safe()

    # if we were not able to find a usable dense cell, try to find a random one
    if move == "o":
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} Collision, trying to find a random move".format(
                    ship.id))
        lateral_offsets = Direction.laterals(move_offset)
        lateral_moves = list(
            map(lambda direction_offset: Direction.convert(direction_offset),
                lateral_offsets))
        move = get_random_move(game, ship, lateral_moves)

    if move == "o":
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} Collision, unable to find a move".format(
                    ship.id))

    move_plus_one = Position(
        best_cell.position.x,
        best_cell.position.y)  # go one more move in the same direction
    if DEBUG & (DEBUG_NAV):
        logging.info("Nav - Ship {} has a move_plus_one of {}".format(
            ship.id, move_plus_one))
    ship.path.append(move_plus_one)

    return move