Ejemplo n.º 1
0
def getClosestSpot(ship):
    possible = []
    cleanPlaces(targetArea)
    for i in targetArea:
        if i != ship.position:
            pickDir = game_map.get_unsafe_moves(ship.position, i)[0]
            if ((pickDir).__ne__(Direction.Still)) and (ship.position.__ne__(
                    i)) and game_map[i].halite_amount > 100:
                possible.append(i)

    if len(possible) > 0:
        closest = possible[0]
        for i in possible:
            if game_map.calculate_distance(ship.position,
                                           i) < game_map.calculate_distance(
                                               ship.position, closest):
                if game_map.get_unsafe_moves(ship.position,
                                             i)[0] != Direction.Still:
                    closest = i

        return Direction.convert(
            game_map.get_unsafe_moves(ship.position, closest)[0])
    else:
        for i in Direction.get_all_cardinals():
            if (game_map[ship.position.directional_offset(i)].is_occupied ==
                    False):
                return Direction.convert(
                    game_map.get_unsafe_moves(
                        ship.position, ship.position.directional_offset(i))[0])
def get_random_move(ship):

    moveChoice = random.choice(["n", "s", "e", "w"])
    #logging.info("Ship - get_random_move() - ship {} moveChoice2: {}".format(ship.id, moveChoice))

    moveOffset = ship.position.directional_offset(DIRECTIONS[moveChoice])
    #logging.info("Ship - get_random_move() - ship {} moveOffset2: {}".format(ship.id, moveOffset))

    move = Direction.convert(game_map.naive_navigate(ship, moveOffset))
    #logging.info("Ship - get_random_move() - ship {} final move2: {}".format(ship.id, move))

    if move == "o":
        original_move = move
        for i in range(4):
            # get char direction vs alt code below so we can log consistent msg
            # alt code: ship.move(random.choice([Direction.North, Direction.South, Direction.East, Direction.West]))
            moveChoice = random.choice(["n", "s", "e", "w"])
            moveOffset = ship.position.directional_offset(
                DIRECTIONS[moveChoice])
            move = Direction.convert(game_map.naive_navigate(ship, moveOffset))
            if move != "o":
                break

        if move == "o":
            logging.info(
                "Ship - get_random_move() - ship {} Collision, original {}, correct failed"
                .format(ship.id, original_move))
        else:
            logging.info(
                "Ship - get_random_move() -  ship {} Collision, original {}, corrected {}"
                .format(ship.id, original_move, move))

    return move
def get_dense_move(ship):
    moves = []
    for d in ship.position.get_surrounding_cardinals():
        if game_map[
                d].halite_amount > constants.MAX_HALITE / 10 and not ship.is_full:
            moves.append((d.x, d.y, game_map[d].halite_amount))

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

    logging.info(
        "Ship - get_dense_move() - sorted_moves {}".format(sorted_moves))

    if len(sorted_moves) == 0:
        move = get_random_move(ship)
    else:
        pos = Position(sorted_moves[0][0] - ship.position.x,
                       sorted_moves[0][1] - ship.position.y)
        logging.info("Ship - ship {} get_dense_move() - pos {}".format(
            ship.id, pos))

        moveOffset = game_map.normalize(pos)
        logging.info("Ship - ship {} get_dense_move() - moveOffset {}".format(
            ship.id, moveOffset))

        move = Direction.convert(
            game_map.naive_navigate(ship, ship.position + moveOffset))
        logging.info("Ship - ship {} get_dense_move() - move {}".format(
            ship.id, move))

        if move == "o":
            for i in range(1, len(sorted_moves)):
                moveOffset = game_map.normalize(
                    Position(sorted_moves[i][0] - ship.position.x,
                             sorted_moves[i][1] - ship.position.y))

                logging.info(
                    "Ship - ship {} get_dense_move() - moveOffset {}".format(
                        ship.id, moveOffset))

                move = Direction.convert(
                    game_map.naive_navigate(ship, moveOffset))
                if move != "o":
                    break

    if move == "o":
        logging.info("Ship - ship {} get_dense_move() - noop".format(ship.id))

    return move
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
 def get_best_move(self, move_dict, description, crash_base=False):
     for ship in move_dict:
         if ship.id in self.can_not_move:
             #Can't move
             self.commands.append(f'm {ship.id} o')
             self.moves.append(str(ship.position))
             continue
         for i in range(len(move_dict[ship])):
             if self.valid_move(move_dict[ship][i][2]):
                 # logging.info(f"VALID MOVE {description} Ship ID: {ship.id} H/M/P: {move_dict[ship][i]}")
                 self.moves.append(str(move_dict[ship][i][2]))
                 direction = Direction.convert(move_dict[ship][i][1])
                 self.commands.append(f'm {ship.id} {direction}')
                 break
             else:
                 if crash_base == True and move_dict[ship][i][0] == 0:
                     self.moves.append(str(move_dict[ship][i][2]))
                     direction = Direction.convert(move_dict[ship][i][1])
                     self.commands.append(f'm {ship.id} {direction}')
                     break
Ejemplo n.º 6
0
 def _get_homing_next_move(self, shippos, gmap):
     drops = self.game.me.get_dropoffs()
     drops.append(self.game.me.shipyard)  # trying to add shipyard
     near_drop = drops[0]
     for drop in drops:
         if gmap.calculate_distance(
                 shippos, drop.position) < gmap.calculate_distance(
                     shippos, near_drop.position):
             near_drop = drop
     return Direction.convert(
         gmap.naive_navigate(self.ship, near_drop.position))
Ejemplo n.º 7
0
def get_command(game_map, ship, shipyard):
    best_neighbor_position = None
    best_neighbor_direction = None
    max_halite = 0
    current_halite = game_map[ship.position].halite_amount

    # Get the nearest neighbor positions and check their halite amounts
    for neighboring_position in ship.position.get_surrounding_cardinals():
        halite_amt = game_map[neighboring_position].halite_amount
        is_occupied = game_map[neighboring_position].is_occupied

        if (best_neighbor_position is None or halite_amt > max_halite) and not is_occupied:
            max_halite = halite_amt
            best_neighbor_position = neighboring_position
            best_neighbor_direction = game_map.naive_navigate(ship, best_neighbor_position)

    if max_halite == 0:
        # We're surrounded by zero. Pick a random direction for now. We should be smarter about picking targets.
        best_neighbor_direction = random.choice([Direction.North, Direction.South])

    if best_neighbor_position is None:
        # We've been trapped? There is no best position after checking all four
        # For now we'll crash to the right to see if we can free up the situation
        best_neighbor_direction = Direction.East

    logging.info('Max halite nearby: {} direction: {}'.format(
        max_halite, Direction.convert(best_neighbor_direction)))
    logging.info('Halite storage is at {}'.format(ship.halite_amount))
    logging.info('Current halite at this position: {}'.format(current_halite))

    two_turn_stay_ev, two_turn_move_ev = get_future_ev(current_halite, max_halite)

    if two_turn_stay_ev > two_turn_move_ev:
        # Better to stay
        logging.info("I should stay here. EV={} vs {}".format(
            current_halite * .25 + current_halite * (.75 * .25),
            max_halite * .25 - current_halite * .1
        ))
        return ship.stay_still()
    else:
        logging.info("I should move. EV={} vs {}".format(
            current_halite * .25 + current_halite * (.75 * .25),
            max_halite * .25 - current_halite * .1
        ))
        return ship.move(best_neighbor_direction)
Ejemplo n.º 8
0
def endGame(ship):
    Dir = game_map.get_unsafe_moves(ship.position,
                                    game_map[me.shipyard].position)
    #print(Dir)
    moveDir = Direction.Still
    if len(Dir) > 0:

        if (ship.position.directional_offset(Dir[0])).__eq__(
                game_map[me.shipyard].position):

            moveDir = game_map.get_unsafe_moves(
                ship.position, game_map[me.shipyard].position)[0]
            #print(moveDir)
        else:
            moveDir = game_map.naive_navigate(ship,
                                              game_map[me.shipyard].position)
    command_queue.append(ship.move(Direction.convert(moveDir)))
    return 0
Ejemplo n.º 9
0
def get_closest_dropoff_move(game_map, ship, dropoff_positions):
    distances = []
    for dropoff in dropoff_positions:
        distance = game_map.calculate_distance(ship.position, dropoff)
        distances.append((distance, dropoff))

    distances = sorted(distances, key=lambda x: x[0])
    logging.debug(f"Distances: {distances}")

    closest_dropoff = distances[0]

    move = game_map.naive_navigate(ship, closest_dropoff[1])
    logging.info("Closest Dropoff: {} -> {}, distance {}, move {}".format(
        ship.position,
        closest_dropoff[1],
        closest_dropoff[0],
        Direction.convert(move)
    ))
    if move == Direction.Still:
        logging.warning("This shouldn't happen, the nearest dropoff is current position?")

    return move
                ship.status = "exploring"
            else:
                dropoffs = me.get_dropoffs()
                destinations = list(dropoffs) + [me.shipyard.position]

                minDistance = False
                movePosition = False
                move = False

                for dest in destinations:
                    distance = game_map.calculate_distance(ship.position, dest)
                    if minDistance == False or distance < minDistance:
                        minDistance = distance
                        movePosition = dest

                move = Direction.convert(
                    game_map.naive_navigate(ship, movePosition))

                logging.info("Ship - Ship {} initial move1: {}".format(
                    ship.id, move))

                if move == "o":
                    logging.info("Ship - Ship {} Collision returning".format(
                        ship.id))
                    ship.status = "backingoff"
                    ship.path.append(getBackoffPoint(game, ship, dest))
                else:
                    fuelCost = round(
                        game_map[ship.position].halite_amount * .1, 2)
                    if fuelCost > ship.halite_amount:
                        logging.info(
                            "Ship - Ship {} has insuffient fuel. Have {}, need {}"
Ejemplo n.º 11
0
def get_halite_move(game, ship, args=None):
    """
    Get a move based on the surrounding cell with the most halite

    :param args None ... for now.
    :returns Returns a move letter on success, None if there is a collision.
    """
    if args is None:
        args = {}

    move = "o"

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

    sorted_blocks = get_best_blocks(game, ship, 3, 3)

    if not sorted_blocks:
        old_threshold = ship.mining_threshold
        ship.mining_threshold = 25
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - ship {} Best block search failed 1.  All surrounding cells have halite < threshold({}). Setting mining_threshold to {} and retrying. t{}"
                .format(ship.id, old_threshold, ship.mining_threshold,
                        game.turn_number))
        sorted_blocks = get_best_blocks(game, ship, 3, 3)
        if not sorted_blocks:
            move = get_random_move(
                game,
                ship)  # ToDo: would be better to try a large search radius?
            if DEBUG & (DEBUG_NAV):
                logging.info(
                    "Nav - ship {} Best block search failed 2. All surrounding cells have halite < threshold({}) . Returning random move: {}. t{}"
                    .format(ship.id, ship.mining_threshold, move,
                            game.turn_number))
            return move

    best_bloc_data = sorted_blocks[
        0]  # (directional_offset, block, block mean value)
    max_cell_amount = best_bloc_data[1].get_max()

    if DEBUG & (DEBUG_NAV_VERBOSE):
        logging.info(
            "Nav - ship {} found {} valid halite cells with a the max cell containing {} halite"
            .format(ship.id, len(sorted_blocks), max_cell_amount))

    for best_cell in best_bloc_data[1].get_cells():
        if best_cell.halite_amount == max_cell_amount:
            break

    move_offset = best_bloc_data[0]

    new_position = game.game_map.normalize(
        ship.position.directional_offset(move_offset))

    normalized_position = game.game_map.normalize(new_position)

    cell = game.game_map[normalized_position]

    if DEBUG & (DEBUG_NAV_VERBOSE):
        logging.info(
            "Nav - Ship {} next cell: {}, offset: {}, value: {}".format(
                ship.id, normalized_position, move_offset, cell.halite_amount))

    #
    # collision resolution
    #
    if cell.is_occupied:
        game.collisions.append(
            (ship, cell.ship, Direction.convert(move_offset),
             normalized_position, resolve_halite_move))  # args = alt moves?
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - ship {} collided with ship {} at {} while moving {}".
                format(ship.id, cell.ship.id, normalized_position,
                       Direction.convert(move_offset)))
        return None

    #
    # success
    #
    cell.mark_unsafe(ship)
    move = Direction.convert(move_offset)

    # blocks are guaranteed to have at least 1 cell that is minable. This is critical to avoid getting stuck
    # between two blocks each of which is never modified.  For a 3x3 block, add 'plus_one' assures that we move
    # far enough to reach the modifiable cell, thus preventing an endless movement between blocks
    move_plus_one = Position(
        best_cell.position.x,
        best_cell.position.y)  # go one more move in the same direction
    if cell.position != move_plus_one:
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} has a plus_one move of {}, halite: {}".format(
                    ship.id, move_plus_one, max_cell_amount))
        ship.path.append(move_plus_one)

    return move
Ejemplo n.º 12
0
def get_nav_move(game, ship, args=None):
    """
    Get a move based on the exist ship.path

    :param game
    :param ship
    :param args
    :returns Returns a move letter on success, None if there is a collision.
    """

    if args is None:
        args = {}

    waypoint_resolution = args[
        "waypoint_resolution"] if "waypoint_resolution" in args else "astar"
    move_cost = args["move_cost"] if "move_cost" in args else "turns"

    game_map = game.game_map

    if DEBUG & (DEBUG_NAV_VERBOSE):
        logging.info(
            "Nav - ship {} Getting nav move, path: {}, waypoint resolution: {}, move_cost: {}"
            .format(ship.id, list_to_short_string(ship.path, 4),
                    waypoint_resolution, move_cost))

    ship_cell = game_map[ship]

    if not ship.path:
        if DEBUG & (DEBUG_NAV):
            logging.warn(
                "Nav - ship {} Getting nav path. Empty path. Returning 'o'. t{}"
                .format(ship.id, game.turn_number))
        if ship_cell.is_occupied:
            game.collisions.append((ship, ship_cell.ship, 'o', ship.position,
                                    resolve_nav_move))  # args = ?
            if DEBUG & (DEBUG_NAV):
                logging.info(
                    "Nav - Ship {} collided with ship {} at {} while moving {}"
                    .format(ship.id, ship_cell.ship.id, ship.position, 'o'))
            return None
        else:
            ship_cell.mark_unsafe(ship)
            return 'o'

    next_position = 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 {} Getting nav path. 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_resolution,
                                       {"move_costs": move_cost})

        if path is None or len(path) == 0:
            if DEBUG & (DEBUG_NAV):
                logging.warn(
                    "Nav - ship {} Nav failed, can't reach waypoint {} from {}"
                    .format(ship.id, normalized_next_position, ship.position))
            if ship_cell.is_occupied:
                game.collisions.append(
                    (ship, ship_cell.ship, 'o', ship.position,
                     resolve_nav_move))  # args = ?
                if DEBUG & (DEBUG_NAV):
                    logging.info(
                        "Nav - Ship {} collided with ship {} at {} while moving {}"
                        .format(ship.id, ship_cell.ship.id, ship.position,
                                'o'))
                return None
            else:
                ship_cell.mark_unsafe(ship)
                return 'o'
        else:
            if DEBUG & (DEBUG_NAV_VERBOSE):
                logging.info(
                    "Nav - ship {} path to waypoint {} found. Length: {}, cost: {}"
                    .format(ship.id, next_position, len(path), round(cost)))
            ship.path.pop()
            ship.path = ship.path + path

    new_position = ship.path[-1]

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

    # why?
    if normalized_new_position == ship.position:
        if DEBUG & (DEBUG_NAV):
            logging.warn(
                "Nav - ship {} popped move {}. Returning 'o'.  Why did this happen?"
                .format(ship.id, ship.path[-1]))
        ship.path.pop()
        game_map[ship].mark_unsafe(ship)
        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_VERBOSE):
        logging.info("Nav - Ship {} has potential nav move: {}".format(
            ship.id, move))

    #
    # collision resolution
    #
    if cell.is_occupied:
        game.collisions.append((ship, cell.ship, move, normalized_new_position,
                                resolve_nav_move))  # args = ?
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - Ship {} collided with ship {} at {} while moving {}".
                format(ship.id, cell.ship.id, normalized_new_position, move))
        return None

    #
    # success
    #
    cell.mark_unsafe(ship)
    if DEBUG & (DEBUG_NAV_VERBOSE):
        logging.info("Nav - ship {} popped nav path {}".format(
            ship.id, ship.path[-1]))
    ship.path.pop()

    return move
Ejemplo n.º 13
0
        else:
            # For each of your ships, move randomly if the ship is on a low halite location or the ship is full.
            #   Else, collect halite.
            ship_x, ship_y = ship.position.x, ship.position.y
            ship_utility = deepcopy(
                game_utility_grid[ship_x][ship_y].utilities)
            ship_utility.sort(key=by_halite, reverse=True)
            for i in range(5):
                if game_map[ship.position.directional_offset(
                        ship_utility[i]
                    [0])].is_occupied and ship.position.directional_offset(
                        ship_utility[i][0]) != ship.position:
                    logging.info("continues")
                    continue
                else:
                    if Direction.convert(ship_utility[i][0]) == "o":
                        logging.info("still at %s", ship.stay_still())
                        command_queue.append(ship.stay_still())
                    else:
                        logging.info("logging %s", ship_utility[i][0])
                        command_queue.append(ship.move(ship_utility[i][0]))
                    break

        # if game_map[ship.position].halite_amount < constants.MAX_HALITE / 10 or ship.is_full:
        #     command_queue.append(
        #         ship.move(
        #             random.choice([ Direction.North, Direction.South, Direction.East, Direction.West ])))
        # else:
        #     command_queue.append(ship.stay_still())

    # If the game is in the first 200 turns and you have enough halite, spawn a ship.
Ejemplo n.º 14
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
                # Debug metric, can't use position because will be for diff ship/position every time
                #DebugMetrics["loiterOffsets"].append((loiterOffset.x, loiterOffset.y))
                #DebugMetrics["loiterDistances"].append((game.turn_number, round(math.sqrt(loiterOffset.x ** 2 + loiterOffset.y ** 2), 2)))

                loiterPoint = ship.position + loiterOffset

                #logging.info("Ship - backoff/loiter point: {}".format(loiterPoint))

                ship.path.append(loiterPoint)

                ship.status = "exploring"
            else:
                dropoff_position = get_dropoff_position(ship)

                move = Direction.convert(
                    game_map.naive_navigate(ship, dropoff_position))

                logging.info("Ship - Ship {} initial move1: {}".format(
                    ship.id, move))

                if move == "o":
                    logging.info("Ship - Ship {} Collision returning".format(
                        ship.id))
                    ship.status = "backingoff"
                    ship.path.append(
                        get_backoff_point(game, ship, dropoff_position))
                else:
                    fuelCost = round(
                        game_map[ship.position].halite_amount * .1, 2)
                    if fuelCost > ship.halite_amount:
                        logging.info(
Ejemplo n.º 16
0
    for ship in me.get_ships():
        logging.info("Ship {} has {} halite with status {} and number of dropoffs {}.".format(
            ship.id, ship.halite_amount, ship_status[ship.id], len(me.get_dropoffs())))

        # make the ship a drop off
        myDist = game_map.calculate_distance(
            ship.position, me.shipyard.position)

        # suicide bots run into the shipyard in the last to deposit halite
        ## This is the fastest way to get all ships to empty cargo at once
        if game.turn_number > 470:
            if ship.position == me.shipyard.position:
                command_queue.append(ship.stay_still())
            elif myDist <2:
                myUnSafe = game_map.get_unsafe_moves(ship.position, me.shipyard.position)
                move = Direction.convert(myUnSafe[0])
                command_queue.append(ship.move(move))
                logging.info("unSafe moves: {}".format(move))

            else:
                move = game_map.naive_navigate(ship, me.shipyard.position)
                command_queue.append(ship.move(move))

        # turn a ship into a dropoff when game is not too far in 
        # AND the ship is far enough away from the shipyard
        # AND the play can afford to spend 4000 on a dropoff
        elif (game.turn_number <= 330 and count == 0 and me.halite_amount > 6000 and myDist > 15 
        and game_map[ship.position].halite_amount > 500):
            count = count + 1
            logging.info("ship {} is creating drop off @ {} with distance {}".format(
                ship.id, ship.position, myDist))
Ejemplo n.º 17
0
def pathfind(ship, m, unpassable: list):
    ''' 
    Determines the best route to target using astar.
    Start and target are Position objects
    '''

    size = m.shape[0]

    # Get the ship position
    start = ship.position

    # Get the target
    target = ship.target

    # Start position coord tupple
    sx, sy = start.x, start.y

    # Target position coord tupple
    tx, ty = target.x, target.y

    # Get adjacent squares (list with Position objects)
    adj = start.get_surrounding_cardinals()

    # Remove adjacent squares that are unpassable (occupied)
    # logging.info("Ship {}: Unpassable {}".format(ship.id, unpassable))
    adj = [a for a in adj if a not in unpassable.values()]

    # See if ship can get out of the square
    # If not, return the same position
    # If no squares are available, stay still
    # And add current position to the unpassable list
    if (ship.halite_amount < round(0.1 * m[sy, sx]) or not adj):
        logging.info(
            "Ship {} on square {} with hal: {} needs {} to move and has {}".
            format(ship.id, (sx, sy), m[sy, sx], 0.1 * m[sy, sx],
                   ship.halite_amount))
        unpassable[ship.id] = start
        return 'o', unpassable

    # All the tiles with hal < htresh have value 0
    m[m < htresh] = 0

    # Sort Positions by value
    # Get position as tupple
    adj = [(pos.y, pos.x) for pos in adj]

    # Sort the positions based on val
    adj = sorted(adj, key=lambda c: val(c, (ty, tx), m))[0]

    # Replace with the navigate function
    # Get the best direction
    d_tuple = (adj[1] - sx, adj[0] - sy)
    # logging.info("{}".format(d_tuple))

    # need to normalize the tuple in case of something like (0, -31)
    # Probably not the most efficient way of doing this
    if max([abs(a) for a in d_tuple]) == size - 1:
        d_tuple = tuple([int(a / -(size - 1)) for a in d_tuple])

    direction = Direction.convert(d_tuple)

    # Append new position to unpassable
    unpassable[ship.id] = (start.directional_offset(d_tuple))

    return direction, unpassable
Ejemplo n.º 18
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
Ejemplo n.º 19
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
Ejemplo n.º 20
0
def getBack(ship, drop):
    possPos = []
    returning = 1
    mustGetBack = False
    same = False
    for dir in game_map.get_unsafe_moves(ship.position, drop):
        possPos.append(ship.position.directional_offset(dir))
    if ship.position.x == drop.x and ship.position.y == drop.y:
        possPos.append(ship.position)
        same = True
    if ship.id not in shipsToReturn:
        returning = -1
    if returning == 1 and remainingTurns - game_map.calculate_distance(
            ship.position, locateClosestDropoff(ship)) <= 10:
        mustGetBack = True
    min = possPos[0]
    last = shipsbeen[ship.id]
    # Min for returning, make sure that it doesn't go into the enemy territory if possible
    # Max not returning, make sure that it doesn't go into the enemy territory if possible
    for pos in possPos:
        if (returning == 1
                and game_map[pos].halite_amount < game_map[min].halite_amount
                and pos not in nogozone
                and last != pos) or (min in nogozone
                                     and pos not in nogozone) or (min == last):
            min = pos
        elif (returning == -1
              and game_map[pos].halite_amount > game_map[min].halite_amount
              and pos not in nogozone
              and last != pos) or (min in nogozone
                                   and pos not in nogozone) or (min == last):
            min = pos
    moves = game_map.get_unsafe_moves(ship.position, min)
    min = game_map.normalize(min)
    if not same:
        # Move if my ship isnt in the way
        if nextmap[min.x][min.y] == -1 or (nextmap[min.x][min.y] == -2
                                           and min == drop):
            command_queue.append(ship.move(Direction.convert(moves[0])))
            shipsOrdered.append(ship.id)
            nextmap[min.x][min.y] = ship.id
            nextmap[ship.position.x][ship.position.y] = -1
            shipsbeen[ship.id] = Position(-1, -1)
        elif nextmap[min.x][min.y] == -2:
            badpos = list(
                map(
                    lambda x: game_map.normalize(
                        ship.position.directional_offset(Direction.invert(x))),
                    game_map.get_unsafe_moves(ship.position, drop)))
            if returning == 1:
                max = 22000
                maxpos = Position(-1, -1)
            else:
                max = -5
                maxpos = Position(-1, -1)
            for pos in ship.position.get_surrounding_cardinals():
                temp = game_map.normalize(pos)
                if temp not in badpos and nextmap[temp.x][temp.y] == -1:
                    if returning == 1 and game_map[
                            temp].halite_amount < max and temp != last:
                        max = game_map[temp].halite_amount
                        maxpos = temp
                    elif returning == -1 and game_map[
                            temp].halite_amount > max and temp != last:
                        max = game_map[temp].halite_amount
                        maxpos = temp
            if (returning == 1 and max < 22000) or (returning == -1
                                                    and max > -5):
                command_queue.append(
                    ship.move(
                        Direction.convert(
                            game_map.get_unsafe_moves(ship.position,
                                                      maxpos)[0])))
                shipsOrdered.append(ship.id)
                nextmap[ship.position.x][ship.position.y] = -1
                nextmap[maxpos.x][maxpos.y] = ship.id
                shipsbeen[ship.id] = ship.position
            else:
                command_queue.append(ship.stay_still())
                shipsOrdered.append(ship.id)
                shipsToStay.append(ship.id)
                shipsbeen[ship.id] = Position(-1, -1)
        elif mustGetBack and (min == me.shipyard.position or min in list(
                map(lambda x: x.position, me.get_dropoffs()))):
            command_queue.append(ship.move(Direction.convert(moves[0])))
            shipsOrdered.append(ship.id)
            nextmap[min.x][min.y] = ship.id
            nextmap[ship.position.x][ship.position.y] = -1
            shipsbeen[ship.id] = Position(-1, -1)
        # When you don't want to swap since it would make the other ship further from goal
        elif ship.id not in shipsToReturn and nextmap[min.x][
                min.y] >= 0 and game_map.calculate_distance(
                    ship.position, shiptargets[nextmap[min.x][
                        min.y]]) > game_map.calculate_distance(
                            min, shiptargets[nextmap[min.x][min.y]]):
            if game_map[ship.position].halite_amount < halitethreshold:
                #something I put in for testing purposes, get rid of it if it's bad
                # Don't just sit there if there's someone ahead and the cell is almost empty, move to nearest highest halite location
                max = game_map[ship.position].halite_amount
                maxpos = ship.position
                for pos in ship.position.get_surrounding_cardinals():
                    pos = game_map.normalize(pos)
                    if nextmap[pos.x][
                            pos.y] == -1 and game_map[pos].halite_amount > max:
                        max = game_map[pos].halite_amount
                        maxpos = pos
                if maxpos != ship.position and (max >= halitethreshold
                                                or ship.position
                                                == me.shipyard.position):
                    command_queue.append(
                        ship.move(
                            game_map.get_unsafe_moves(ship.position,
                                                      maxpos)[0]))
                    shipsOrdered.append(ship.id)
                    nextmap[maxpos.x][maxpos.y] = ship.id
                    nextmap[ship.position.x][ship.position.y] = -1
            elif ship.position != me.shipyard.position:
                command_queue.append(ship.stay_still())
                shipsOrdered.append(ship.id)
                shipsToStay.append(ship.id)
            shipsbeen[ship.id] = Position(-1, -1)
        # Swap positions of ships if first one is higher in priority
        elif nextmap[min.x][min.y] >= 0 and nextmap[min.x][
                min.y] not in shipsToStay and nextmap[min.x][
                    min.y] not in shipsToReturn and nextmap[min.x][
                        min.y] not in shipsOrdered:
            command_queue.append(ship.move(Direction.convert(moves[0])))
            command_queue.append(game.game_map[min].ship.move(
                Direction.invert(moves[0])))
            shipsOrdered.append(ship.id)
            shipsOrdered.append(game.game_map[min].ship.id)
            nextmap[ship.position.x][
                ship.position.y] = game.game_map[min].ship.id
            nextmap[min.x][min.y] = ship.id
            shipsbeen[ship.id] = Position(-1, -1)
    else:
        # if the destination is reached and it has less than 10 halite, go to the nearest highest halite square
        if game_map[drop].halite_amount < halitethreshold and (
                drop.x, drop.y) not in forecast:
            max = game_map[drop].halite_amount
            maxpos = ship.position
            for pos in ship.position.get_surrounding_cardinals():
                pos = game_map.normalize(pos)
                if nextmap[pos.x][pos.y] == -1 and game_map[
                        pos].halite_amount > game_map[
                            ship.position].halite_amount and game_map[
                                pos].halite_amount > max:
                    max = game_map[pos].halite_amount
                    maxpos = pos
            if max > game_map[drop].halite_amount and max >= halitethreshold:
                command_queue.append(
                    ship.move(
                        game_map.get_unsafe_moves(ship.position, maxpos)[0]))
                shipsOrdered.append(ship.id)
                nextmap[maxpos.x][maxpos.y] = ship.id
                nextmap[ship.position.x][ship.position.y] = -1
            else:
                command_queue.append(ship.stay_still())
                shipsOrdered.append(ship.id)
                shipsToStay.append(ship.id)
        else:
            command_queue.append(ship.stay_still())
            shipsOrdered.append(ship.id)
            shipsToStay.append(ship.id)
        shipsbeen[ship.id] = Position(-1, -1)
Ejemplo n.º 21
0
def get_halite_move(game, ship, args=None):
    """
    Get a move based on the surrounding cell with the most halite

    :param args None ... for now.
    :returns Returns a move letter on success, None if there is a collision.
    """
    if args is None:
        args = {}

    move = "o"

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

    moves = []
    for blocks in game.game_map.get_cell_blocks(
            ship.position, 3,
            3):  # returns array of tuples [(direction), CellBlock]
        directional_offset = blocks[0]
        block = blocks[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 not sorted_blocks:
        move = get_random_move(
            game, ship)  # ToDo: would be better to try a large search radius?
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - ship {} All surrounding cells have halite < {} . Returning random move: {}"
                .format(ship.id, constants.MAX_HALITE * MINING_THRESHOLD_MULT,
                        move))
        return move

    best_bloc_data = sorted_blocks[
        0]  # (directional_offset, block, block mean value)
    max_cell_amount = best_bloc_data[1].get_max()

    if DEBUG & (DEBUG_NAV):
        logging.info(
            "Nav - ship {} found {} valid halite cells with a the max cell containing {} halite"
            .format(ship.id, len(sorted_blocks), max_cell_amount))

    for best_cell in best_bloc_data[1].get_cells():
        if best_cell.halite_amount == max_cell_amount:
            break

    move_offset = best_bloc_data[0]

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

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

    cell = game.game_map[normalized_position]

    #
    # collision resolution
    #
    if cell.is_occupied:
        game.collisions.append(
            (ship, cell.ship, Direction.convert(move_offset),
             normalized_position, resolve_halite_move))  # args = alt moves?
        if DEBUG & (DEBUG_NAV):
            logging.info(
                "Nav - ship {} collided with ship {} at {} while moving {}".
                format(ship.id, cell.ship.id, normalized_position,
                       Direction.convert(move_offset)))
        return None

    #
    # success
    #
    cell.mark_unsafe(ship)
    move = Direction.convert(move_offset)

    # blocks are guaranteed to have at least 1 cell that is minable. This is critical to avoid getting stuck
    # between two blocks each of which never modified.  For a 3x3 block, add 'plus_one' assures that we move far
    # to reach the modifiable cell, thus prevent an endless movement between blocks
    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