Esempio n. 1
0
    def moveShipSmart(self, ship, target, unsafe=False):
        # Used for seen and keeps track of which cell the best path came from
        # Except for initial cells which contain direction
        prevCell = dict()
        # Cells still to be searched
        toSearch = list()

        def cost(halite, distance):
            adjustedInv = (ship.halite_amount - halite) / fastPow(
                GROWTH, distance)
            return ship.halite_amount - adjustedInv

        def heuristic(pos, halite, distance):
            furtherDistance = self.game_map.calculate_distance(target, pos)
            newDistance = distance + furtherDistance
            expHalite = int((MINE_T + MINE_T *
                             (1.0 - 1.0 / constants.EXTRACT_RATIO)) / 2.0)
            newHalite = halite + furtherDistance * expHalite // constants.MOVE_COST_RATIO
            return cost(newHalite, newDistance)

        # Add initial cells to search space
        for dir in Direction.get_all_cardinals():
            newPos = self.game_map.normalize(
                ship.position.directional_offset(dir))
            halite = self.game_map[
                ship.position].halite_amount // constants.MOVE_COST_RATIO
            distance = 1
            Cost = cost(halite, distance)
            heapq.heappush(toSearch, (heuristic(
                newPos, halite, distance), halite, distance, newPos))
            prevCell[newPos] = (Cost, ship.position, dir)

        curr = target
        # Search for target
        while toSearch:
            adjCost, halite, distance, pos = heapq.heappop(toSearch)
            if pos == target:
                curr = pos
                break
            for dir in Direction.get_all_cardinals():
                newPos = self.game_map.normalize(pos.directional_offset(dir))
                newHalite = halite + self.game_map[
                    pos].halite_amount // constants.MOVE_COST_RATIO
                newDistance = distance + 1
                Cost = cost(newHalite, newDistance)
                if newPos not in prevCell:
                    heapq.heappush(toSearch,
                                   (heuristic(newPos, newHalite, newDistance),
                                    newHalite, newDistance, newPos))
                    prevCell[newPos] = (Cost, pos, dir)
                else:
                    prevCell[newPos] = min(prevCell[newPos], (Cost, pos, dir))
            logging.info(prevCell)

        # Find original cell
        while prevCell[curr][1] != ship.position:
            logging.info(curr)
            curr = prevCell[curr][1]

        return self.moveShip(ship, prevCell[curr][2])
Esempio n. 2
0
    def moveShipSmart(self, ship, target, unsafe=False):
        seen = set()
        toSearch = list()  # Priority Queue

        def cost(pos):
            return squareCost(self.getHalitePos(pos))

        def heuristic(pos):
            return self.game_map.calculate_distance(target, pos) * 10

        # Initialize queue
        for dir in Direction.get_all_cardinals():
            newPos = self.game_map.normalize(
                ship.position.directional_offset(dir))
            heapq.heappush(toSearch, (cost(ship.position) + heuristic(newPos) -
                                      heuristic(ship.position), newPos, dir))

        # Go through the search queue
        while toSearch:
            c, pos, dir = heapq.heappop(toSearch)
            if pos in seen:
                continue
            seen.add(pos)
            if pos == target:
                if self.moveShip(ship, dir):
                    return True
                return False
            else:
                for d in Direction.get_all_cardinals():
                    newPos = self.game_map.normalize(pos.directional_offset(d))
                    if newPos not in seen:
                        heapq.heappush(toSearch,
                                       ((c + cost(pos) + heuristic(newPos) -
                                         heuristic(pos), newPos, dir)))
Esempio n. 3
0
    def findTarget(self, startHalite, start, maxDis=10):
        toSearch = deque()
        seen = set()

        def evalPoint(halite, distance, pos):
            r_dis = self.game_map.calculate_distance(pos, start)
            adjHalite = halite - r_dis * MINE_T // constants.MOVE_COST_RATIO
            return adjHalite / pow(GROWTH_RATE, distance + r_dis)

        # Format = (halite, distance, pos)
        dHal, dDis = squareCost(self.command.game_map[start].halite_amount)
        toSearch.append((startHalite + dHal, dDis, start))
        seen.add(start)
        best = (evalPoint(halite + dHal, dDis, start), start)

        while toSearch:
            halite, dis, pos = heapq.heappop(toSearch)

            if self.command.game_map.calculateDistance(
                    pos, start) < maxDis and newHalite < RETURN_T:
                for dir in Direction.get_all_cardinals():
                    newPos = self.command.game_map.normalize(
                        pos.get_directional_offset(dir))
                    squareHalite = self.command.game_map[newPos].halite_amount
                    dHalite, dDis = squareCost(squareHalite)
                    newDis = dis + dDis
                    newHalite = min(halite + dHalite, constants.MAX_HALITE)

                    best = max(best, (evalPoint(newHalite, newDis, pos), pos))
                    if newPos not in seen:
                        toSearch.append((newHalite, newDis, newPos))
                        seen.add(newPos)
        if best[1] != start:
            return best[1]
        return start
Esempio n. 4
0
 def findNearTargets(self, ship, maxDis=5):
     toSearch = deque()
     seen = set()
     toSearch.append((0, ship.position))
     seen.add(tup(ship.position))
     bestSquare = (self.command.game_map[ship.position].halite_amount,
                   tup(ship.position))
     while toSearch:
         depth, pos = toSearch.popleft()
         tPos = tup(pos)
         #TODO: modify structure of targets so that it is dict for easier search by position or ship id
         bestSquare = max(
             (self.command.game_map[pos].halite_amount, tup(pos)),
             bestSquare)
         if depth < maxDis:
             for dir in Direction.get_all_cardinals():
                 newPos = self.command.game_map.normalize(
                     pos.directional_offset(dir))
                 newTPos = tup(newPos)
                 if newTPos not in seen:
                     seen.add(newTPos)
                     toSearch.append((depth + 1, newPos))
     if bestSquare[1] != tup(ship.position):
         return bestSquare[1]
     return None
Esempio n. 5
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])
Esempio n. 6
0
    def findNearTarget(self, ship, maxDis=10):
        toSearch = deque()
        seen = set()
        toSearch.append((0, ship.position))
        seen.add(ship.position)

        def metric(pos):
            halite = self.command.getHalitePos(pos)  # - MINE_T
            #distance = (self.command.game_map.calculate_distance(pos, self.command.shipyard.position) + self.command.game_map.calculate_distance(pos, ship.position) + 1)
            distance = (
                self.command.game_map.calculate_distance(pos, ship.position) +
                1)
            return halite / distance

        bestSquare = (metric(ship.position), ship.position)
        while toSearch:
            depth, pos = toSearch.popleft()
            if not self.posAssigned(pos):
                bestSquare = max((metric(pos), pos), bestSquare)
            if depth < maxDis:
                for dir in Direction.get_all_cardinals():
                    newPos = self.command.game_map.normalize(
                        pos.directional_offset(dir))
                    if newPos not in seen:
                        seen.add(newPos)
                        toSearch.append((depth + 1, newPos))
        if bestSquare[1] != ship.position:
            return bestSquare[1]
        return None
Esempio n. 7
0
    def moveShipSmart(self, ship, target, unsafe = False, maxDepth = 10):
    

        # Used for seen and keeps track of which cell the best path came from
        # Except for initial cells which contain direction
        prevCell = dict()
        # Cells still to be searched
        toSearch = list()

        # We account for cost of current square upon landing in it.
        # So distance is one less than actual distance
        def cost(halite, distance):
            adjustedInv = (ship.halite_amount - halite)/fastPow(GROWTH, distance - 1)
            return ship.halite_amount - adjustedInv

        # Estimate total cost as cost up to this point plus cost assuming
        # some minimum amount of halite in remaining squares
        def heuristic(pos, halite, distance):
            furtherDistance = self.game_map.calculate_distance(target, pos)
            newDistance = distance + furtherDistance
            expHalite = MINE_T
            newHalite = halite + furtherDistance * expHalite // constants.MOVE_COST_RATIO
            return cost(newHalite, newDistance)

        # Add initial cells to search space
        for dir in Direction.get_all_cardinals():
            newPos = self.game_map.normalize(ship.position.directional_offset(dir))
            halite = (self.game_map[ship.position].halite_amount
                    + self.game_map[newPos].halite_amount) // constants.MOVE_COST_RATIO
            distance = 1
            Cost = cost(halite, distance)
            heapq.heappush(toSearch, (heuristic(newPos, halite, distance), halite, distance, newPos))
            prevCell[newPos] = (Cost, ship.position, dir)

        curr = target
        # Search for target
        while toSearch:
            adjCost, halite, distance, pos = heapq.heappop(toSearch)
            if pos == target:
                curr = pos
                break
            for dir in self.game_map.get_unsafe_moves(pos, target):
                newPos = self.game_map.normalize(pos.directional_offset(dir))
                newHalite = halite + self.game_map[newPos].halite_amount // constants.MOVE_COST_RATIO
                newDistance = distance + 1
                Cost = cost(newHalite, newDistance)
                if newPos not in prevCell:
                    heapq.heappush(toSearch, (heuristic(newPos, newHalite, newDistance), newHalite, newDistance, newPos))
                    prevCell[newPos] = (Cost, pos, dir)
                else:
                    prevCell[newPos] = min(prevCell[newPos], (Cost, pos, dir))
            logging.info(prevCell)


        # Find original cell
        while prevCell[curr][1] != ship.position:
            logging.info(curr)
            curr = prevCell[curr][1]

        return self.moveShip(ship, prevCell[curr][2])
Esempio n. 8
0
def get_surrounding_cardinals(pos):
    """
    :return: Returns a list of all positions around this specific position in each cardinal direction
    """
    return [
        pos.directional_offset(current_direction)
        for current_direction in Direction.get_all_cardinals()
    ]
Esempio n. 9
0
 def dir_to_dest(self, pos, dest):
     """ Precondition: 
         position one move away """
     normalized_dest = self.game_map.normalize(dest)
     for d in Direction.get_all_cardinals():
         new_pos = self.game_map.normalize(pos.directional_offset(d))
         if new_pos == normalized_dest:
             return d
     return Direction.Still  # should never happen
Esempio n. 10
0
 def get_valid_position(self, vertex):
     directions = Direction.get_all_cardinals()
     shuffle(directions)
     possible_positions = [
         vertex.directional_offset(direction) for direction in directions
     ]
     for index, position in enumerate(possible_positions):
         if self.tup(position) not in utils.tiles_visited:
             return directions[index]
Esempio n. 11
0
    def get_random_direction(self, ship=None):
        direction_list = Direction.get_all_cardinals()
        direction = random.choice(direction_list)

        if ship is not None:
            if ship.position.directional_offset(direction) == self.game.me.shipyard.position:
                direction_list.remove(direction)
                direction = random.choice(direction_list)

        return direction
Esempio n. 12
0
def get_safe_random_direction(ship: Ship, game_map: GameMap):
    safe_choices = []
    for direction in Direction.get_all_cardinals():
        if not game_map[ship.position.directional_offset(
                direction)].is_occupied:
            safe_choices.append(direction)
    if safe_choices:
        chosen_direction = random.choice(safe_choices)
        game_map[ship.position.directional_offset(
            chosen_direction)].mark_unsafe(ship)
        return chosen_direction
    return None
Esempio n. 13
0
def side_or_side(ship, destination, game_map):
    possible_moves = Direction.get_all_cardinals()
    direct_move = game_map.get_unsafe_moves(ship.position, destination)
    possible_moves.remove(direct_move[0])
    possible_moves.remove(Direction.invert(direct_move[0]))
    next_step = random.choice(possible_moves)
    if game_map[ship.position.directional_offset(
            next_step)].is_occupied is True:
        possible_moves.remove(next_step)
        return possible_moves[0]
    else:
        return next_step
Esempio n. 14
0
def getShipMove(ship,sy):
    bestSpot = []
    best = 0
    amount = 820

    if game_map[game_map.normalize(ship.position)].halite_amount < constants.MAX_HALITE / 35 and (ship.halite_amount < amount ):
        for i in Direction.get_all_cardinals():
            if(game_map[ship.position.directional_offset(i)].is_occupied == False):
                bestSpot.append(game_map[ship.position.directional_offset(i)])

        for i in bestSpot:
            if(i.halite_amount > best):
                
                    #bestDir = game_map.naive_navigate(ship, i.position)
                    best = i.halite_amount
                    bestDir = game_map.get_unsafe_moves(ship.position, i.position)[0]
        
        if best < 50:
            bestDir = Direction.convertStr(random.choice(["n", "s","e","w"]))
        place = game_map[ship.position.directional_offset((bestDir))].position
        inPicked = False
        for i in placepicked:
            if (i.__eq__(place)):
                inPicked = True
        if inPicked == False and game_map[ship.position.directional_offset(bestDir)].is_occupied == False:
            placepicked.append(ship.position.directional_offset(bestDir))
            command_queue.append((ship.move(bestDir)))
        else:
            placepicked.append(ship.position)

            command_queue.append(ship.stay_still())

        #returnCommand = (ship.move(bestDir))
    else:
        if ship.is_full or ship.halite_amount > amount:
            #command_queue.append(game_map.get_unsafe_moves(ship.position, Shipyard)[0])
            placeVal = game_map[ship.position.directional_offset(game_map.get_unsafe_moves(ship.position, Shipyard)[0])].position
            inPicked = False
            for e in placepicked:
                if (placeVal.__eq__(e)):
                    inPicked = True

            if inPicked == True:
                command_queue.append(ship.stay_still())
                placepicked.append(ship.position)
            else:
                command_queue.append(ship.move(game_map.naive_navigate(ship, Shipyard)))
                placepicked.append(placeVal) 
        else:
            command_queue.append(ship.stay_still())
            placepicked.append(ship.position)
Esempio n. 15
0
        def decision(ship):
            # returns a list of priority moves with corresponding destination
            rep = []
            ship_position = ship.position
            ship_halite = ship.halite_amount

            to_assign = set(
                chain([Direction.Still], Direction.get_all_cardinals()))

            for one_move in to_assign.copy():
                if normalize_position(
                        ship_position.directional_offset(
                            one_move)) in basic_occupied_cells:
                    to_assign.remove(one_move)

            map_to_cell = {
                d: ship_position.directional_offset(d)
                for d in to_assign
            }

            def assign(move):
                if move in to_assign:
                    rep.append((move, normalize_position(map_to_cell[move])))
                    to_assign.remove(move)

            def assign_still():
                assign(Direction.Still)

            def go_home():
                home_position = find_closest_home(ship_position)
                moves = game_map.get_unsafe_moves(
                    ship_position,
                    home_position)[::-1]  # invert x/y priority on return
                for move in moves:
                    assign(move)
                if len(moves) == 1:
                    assign_still()
                    my_move = moves[0]
                    to_assign.discard(
                        Direction.invert(my_move)
                    )  # don't walk back, but you can go on the sides

            if ship_halite >= 0:
                go_home()
                assign_still()  # learn to wait in line
                # return rep
            else:
                for move in to_assign:
                    assign(move)

            return rep
Esempio n. 16
0
    def __init__(self):
        game = hlt.Game()
        game.ready("vise")

        self.game = game

        self.ship_spawn_value = (constants.MAX_TURNS / 2)
        self.halite_return_value = (9 * constants.MAX_HALITE / 10)
        self.mining_prioritization_value = 3

        self.direction_order = Direction.get_all_cardinals()
        self.direction_order.append(Direction.Still)
        self.ship_states = defaultdict(lambda: ShipStates.Collecting)

        logging.info("Successfully created bot! My Player ID is {}.".format(game.my_id))
Esempio n. 17
0
 def findNearTarget(self, ship, maxDis=10):
     toSearch = deque()
     seen = set()
     toSearch.append((0, ship.position))
     seen.add(ship.position)
     bestSquare = (self.command.getHalitePos(ship.position), ship.position)
     while toSearch:
         depth, pos = toSearch.popleft()
         if not self.posAssigned(pos):
             bestSquare = max((self.command.getHalitePos(pos) / (depth + 1), pos), bestSquare)
         if depth < maxDis:
             for dir in Direction.get_all_cardinals():
                 newPos = self.command.game_map.normalize(pos.directional_offset(dir))
                 if newPos not in seen:
                     seen.add(newPos)
                     toSearch.append((depth+1, newPos))
     if bestSquare[1] != ship.position:
         return bestSquare[1]
     return None
Esempio n. 18
0
    def _executeOrder(self, ship, order):
        if not order:
            return  # Only happens when no order to give
        command, pos, backup = order
        if command == 'mine':  # Mine a specific target/region
            # At target
            if self.inRegion(ship.position, pos):
                # Mineable
                if self.goodTarget(pos) and ship.halite_amount < RETURN_T:
                    if not self.command.holdShip(ship):
                        # Backup plan
                        self._executeOrder(ship, backup)
                        return
                else:
                    # Ship issued a return order
                    self.unasignShip(ship.id)
                    self.fleetOrders[ship.id] = (
                        'move', self.command.shipyard.position,
                        ('hold', None, ('rand', None, None)))
                    self._executeOrder(ship, self.fleetOrders[ship.id])
            else:
                # Mine if space above threshold
                if self.goodTarget(
                        ship.position) and ship.halite_amount < RETURN_T:
                    if not self.command.holdShip(ship):
                        self._executeOrder(ship, backup)
                        return
                elif ship.halite_amount >= RETURN_T:
                    # Ship issued a return order
                    self.unasignShip(ship.id)
                    self.fleetOrders[ship.id] = (
                        'move', self.command.shipyard.position,
                        ('hold', None, ('rand', None, None)))
                    self._executeOrder(ship, self.fleetOrders[ship.id])
                elif not self.command.moveShipSmart(ship, pos):
                    self._executeOrder(ship, backup)
                    return

        elif command == 'move':  # Move to a specific place
            if ship.position == pos:
                self.issueNewCommand(ship)
            else:
                if not self.command.moveShipSmart(ship, pos):
                    self._executeOrder(ship, backup)
                    return

        elif command == 'hold':  # Stay Still
            if not self.command.holdShip(ship):
                self._executeOrder(ship, backup)
                return

        elif command == 'rand':  # Move in a random direction
            moved = False
            dirs = Direction.get_all_cardinals()
            random.shuffle(dirs)
            for dir in dirs:
                if self.command.moveShip(ship, dir):
                    moved = True
                    break
            if not moved:
                self._executeOrder(ship, backup)
                return

        elif command == 'done':  # Move ship towards home, disregarding crashes
            if not self.command.moveShipTowards(
                    ship, self.command.shipyard.position, unsafe=True):
                self.command.holdShip(ship)

        elif command == 'drop':  # Unimplemented
            a = 1

        else:
            logging.info(f"Illegal Command {command} Given to ship {ship.id}")
Esempio n. 19
0
    def smart_navigate(self, ship, destination):
        ''' 
        Uses A* pathing algorithm to find the "best" path from the ship 
        to the destination. 

        If progress cannot be made towards the target, the ship will stand 
        still unless it must move to prevent crashing into another ship.

        Takes a 'ship' and a 'position'
        '''
        start = utils.tup(ship.position)
        goal = utils.tup(destination)
        # Set of notes already evaluated
        closedSet = set()

        # Set of discovered notes (not evaluated)
        openSet = set()
        openSet.add(start)

        # For each node, node it can most efficiently be reached from
        cameFrom = dict()

        # Cost from start node to that node
        gScore = dict()
        gScore[start] = 0

        # Cost from start node to goal by passing through node - partly heuristic
        fScore = dict()
        fScore[start] = self.heuristic_cost_estimate(start, goal)

        # While we have nodes we have not evaluated
        while len(openSet) != 0:
            # Get lowest fScore
            minValue = math.inf
            current = None
            for node in openSet:
                if fScore[node] < minValue:
                    minValue = fScore[node]
                    current = node

            if current == goal:
                logging.info("arrived at goal")
                return self.reconstruct_path(cameFrom, current)

            openSet.remove(current)
            closedSet.add(current)

            directions = Direction.get_all_cardinals()
            possible_positions = [
                self.detup(current).directional_offset(direction)
                for direction in directions
            ]

            # Go through neighbors of current
            for neighbor in possible_positions:
                # Ignore neighbors we already evaluated
                if self.tup(neighbor) in closedSet:
                    continue

                # Distance from start to neighbor
                tentative_gScore = gScore[current] + self.dist_between(
                    current, self.tup(neighbor))

                # Discovered a new node
                if self.tup(neighbor) not in openSet:
                    openSet.add(self.tup(neighbor))
                elif tentative_gScore >= gScore[self.tup(neighbor)]:
                    continue  # We already had a better path

                cameFrom[self.tup(neighbor)] = current
                gScore[self.tup(neighbor)] = tentative_gScore
                fScore[self.tup(
                    neighbor
                )] = tentative_gScore + self.heuristic_cost_estimate(
                    self.tup(neighbor), goal)
Esempio n. 20
0
                        if target == pos:
                            targetted = True

                    if not targetted:
                        if cost < resources and len(path) != 0 and utils.tup(
                                ship.position.directional_offset(
                                    path[0])) not in utils.tiles_visited:
                            score = (resources - cost)**2.5 / steps_ahead
                            if score > max_score:
                                max_score = score
                                directionToMove = path[0]
                                target = pos
                                foundDirection = True

                    # Get all tiles you can access from it
                    directions = Direction.get_all_cardinals()
                    random.shuffle(directions)
                    possible_positions = [
                        vertex.directional_offset(direction)
                        for direction in directions
                    ]

                    # For each tile, check if we have already visited it. If not, add to the queue
                    for index, position in enumerate(possible_positions):
                        if position not in visited:
                            visited.append(position)
                            L = [
                                position, path + [directions[index]],
                                cost + (.1 * resources)
                            ]
                            queue.append(L)
Esempio n. 21
0
def main():
    """" <<<Game Begin>>> """
    game = hlt.Game()
    game.ready("MyPythonBot")
    logging.info("Successfully created bot! My Player ID is {}.".format(
        game.my_id))
    """ <<<Game Loop>>> """
    ship_targets = {}  # Ship : Position
    ship_states = {}  # Ship : ShipState
    while True:
        game.update_frame()
        me = game.me
        game_map = game.game_map
        ships = me.get_ships()

        # Removing Dead ships
        dead_ships = []
        for ship_id in ship_states:
            if not me.has_ship(ship_id):
                dead_ships.append(ship_id)
        for ds in dead_ships:
            del ship_states[ds]

        position_value_list = game_map.get_cell_values(
            me.shipyard.position, MIN_HALITE)  # (position, value)

        # Targets already assigned
        for p in position_value_list:
            if p[0] in ship_targets.values():
                position_value_list.remove(p)

        next_targets = position_value_list
        next_targets.sort(key=itemgetter(1))  # Prioritizing targets

        # Setting Ship States
        for ship in ships:
            if ship.id not in ship_states:
                ship_targets[ship.id] = next_targets.pop()[0]
                ship_states[ship.id] = ShipStates.Outbound
            elif ship.position == me.shipyard.position:
                ship_targets[ship.id] = next_targets.pop()[0]
                ship_states[ship.id] = ShipStates.Outbound

            if ship_states[ship.id] == ShipStates.Outbound and ship_targets[
                    ship.id] == ship.position:
                ship_states[ship.id] = ShipStates.Collect

            if ship_states[ship.id] == ShipStates.Collect and ship.is_full:
                ship_targets[ship.id] = me.shipyard.position
                ship_states[ship.id] = ShipStates.Inbound

            if ship_states[ship.id] == ShipStates.Inbound and ship_targets[
                    ship.id] == ship.position:
                ship_targets[ship.id] = next_targets.pop()[0]
                ship_states[ship.id] = ShipStates.Outbound

            if constants.MAX_TURNS - game.turn_number == game_map.height / 2:  # TODO improve
                ship_targets[ship.id] = me.shipyard.position
                ship_states[ship.id] = ShipStates.Inbound

        logging.info("SHIPS: {}".format(len(ships)))
        logging.info("SHIPS States: {}".format(ship_states))
        logging.info("SHIPS Targets: {}".format(ship_targets))

        # Commands
        ship_moves = {}  # Ship : Position
        command_queue = []  # Command list

        # Stuck Ships
        for ship in ships:
            if ship.halite_amount < game_map[
                    ship.position].halite_amount / constants.MOVE_COST_RATIO:
                ship_moves[ship.id] = ship.position
                command_queue.append(ship.move(Direction.Still))
                log_move(ship, ship_states[ship.id], ship_targets[ship.id],
                         Direction.Still, "STUCK")

        # Moving Ships
        for ship in ships:
            if ship.id not in ship_moves:
                safe_directions = {}  # {direction : halite}
                priority_list = []  # (direction, halite)
                log_reason = "NONE"

                # Get safe moves:
                for d in Direction.get_all():
                    if game_map.normalize(ship.position.directional_offset(
                            d)) not in ship_moves.values():
                        safe_directions[d] = game_map[game_map.normalize(
                            ship.position.directional_offset(d))].halite_amount

                # Transit order
                if ship_states[ship.id] == ShipStates.Inbound or ship_states[
                        ship.id] == ShipStates.Outbound:
                    for d in game_map.get_unsafe_moves(ship.position,
                                                       ship_targets[ship.id]):
                        if d in safe_directions:
                            priority_list.append((d, safe_directions[d]))
                            log_reason = "NAV"
                        priority_list.sort(key=itemgetter(1))  # Lowest first
                    for d in safe_directions:
                        if d not in priority_list:
                            priority_list.append((d, safe_directions[d]))

                # Collect order
                elif ship_states[ship.id] == ShipStates.Collect:
                    if Direction.Still in safe_directions and game_map[
                            ship.position].halite_amount > MIN_HALITE:
                        priority_list.append(
                            (Direction.Still,
                             safe_directions[Direction.Still]))
                        log_reason = "COLLECT"
                    else:
                        for d in Direction.get_all_cardinals():
                            if d in safe_directions:
                                priority_list.append((d, safe_directions[d]))
                                log_reason = "COL MOV"
                        priority_list.sort(key=itemgetter(1),
                                           reverse=True)  # Highest first

                # NO MOVES
                if len(priority_list) == 0:
                    priority_list.append((Direction.Still, 0))
                    log_reason = "NO MOVE"

                # Make move
                final_direction = (priority_list[0])[0]
                ship_moves[ship.id] = game_map.normalize(
                    ship.position.directional_offset(final_direction))
                command_queue.append(ship.move(final_direction))
                log_move(ship, ship_states[ship.id], ship_targets[ship.id],
                         final_direction, log_reason)

        # Spawning
        if me.halite_amount >= constants.SHIP_COST and game.turn_number < 200:
            shipyard_is_empty = True
            for p in ship_moves.values():
                if p == me.shipyard.position:
                    shipyard_is_empty = False
                    break

            if shipyard_is_empty:
                command_queue.append(me.shipyard.spawn())
                logging.info("___SPAWNED SHIP___")

        logging.info("ALL MOVES: {}".format(ship_moves))
        game.end_turn(command_queue)
Esempio n. 22
0
        else:
            add_move_affinity(moves, ship.stay_still(), 20)'''

        if game.turn_number <= 15:
            if ship_num == 1:
                add_move_affinity(moves, Direction.North, 40)
            if ship_num == 2:
                add_move_affinity(moves, Direction.South, 40)
            if ship_num == 3:
                add_move_affinity(moves, Direction.East, 40)
            if ship_num == 4:
                add_move_affinity(moves, Direction.West, 40)

        # For each of your ships, move randomly if the ship is on a low halite location or the ship is full.
        #   Else, collect halite.
        for direct in Direction.get_all_cardinals(
        ):  # reduces chances of running into each other :)
            pos = ship.position.directional_offset(direct)
            if game_map[pos].is_occupied:
                add_move_affinity(moves, direct, -10000)

        if me.halite_amount > 4000 and 1 < len(me.get_ships()) < 5 and len(
                me.get_dropoffs()) / len(me.get_ships()) <= .5:
            add_move_affinity(moves, ship.make_dropoff(), 40)

        if ship.halite_amount >= 500:
            close_drop = me.shipyard
            # for drop in me.get_dropoffs():  # sets close_drop to the closest dropoff location
            #     if game_map.calculate_distance(ship.position, drop.position) < game_map.calculate_distance(ship.position, close_drop.position):
            #         close_drop = drop
            # if close_drop.position is ship.position:
            #     add_move_affinity(moves, ship.stay_still(), 30)
Esempio n. 23
0
def run():
    global spent_so_far
    destinations = {}
    ships_des = {}

    while True:
        game.update_frame()
        # You extract player metadata and the updated map metadata here for convenience.
        me = game.me
        game_map = game.game_map

        turns_left = constants.MAX_TURNS - game.turn_number
        halite_left = get_halite_amount()
        halite_percent = halite_left / starting_halite_amount
        # astar_cache.clear()
        highs = []
        # spots = PriorityQueue()
        for x, y in itertools.product(range(game_map.width),
                                      range(game_map.height)):
            highs.append(Position(x, y))

        enemy_locations = {
            ship.position
            for i in game.players for ship in game.players[i].get_ships()
            if game.players[i].id != game.my_id
        }

        highs = sorted(highs,
                       key=lambda p: game_map[p].halite_amount,
                       reverse=True)[:LOOK_AMOUNT]
        do_spots = highs[:SO_LOOK_AMOUNT]
        positions_used = set()
        command_queue = []

        ship_queue = me.get_ships()
        for do in me.get_dropoffs():
            pos = do.position
            if pos not in dropoffs:
                dropoffs.append(pos)

        # top10 = [highs.get().position for _ in range(10)]
        # logging.info(top10)

        # sort ships by proximity to shipyard
        ship_queue = sorted(
            ship_queue,
            key=lambda s: game_map.calculate_distance(s.position, syp),
            reverse=True)
        # ship_queue = sorted(ship_queue, key=lambda s: s.id,
        #                     reverse=True)

        dropoff = False
        for ship in ship_queue:

            # is ship in inspired state?
            num_of_enemies = 0
            for x, y in itertools.product(range(-4, 5), range(-4, 5)):
                pos = ship.position.directional_offset((x, y))
                if pos in enemy_locations:
                    num_of_enemies += 1
                if num_of_enemies >= 2:
                    ship.inspired = True
                    break
            else:
                ship.inspired = False

            ship.collect_amount = game_map[ship.position].halite_amount * .25
            if ship.inspired:
                ship.collect_amount += ship.collect_amount * 2  # inspiration bonus

            if ship.id not in first_seen:
                first_seen[ship.id] = game.turn_number
            ship.staying = False
            ship.returning = False
            if ship.position in destinations:
                s = destinations[ship.position]
                del ships_des[s]
                del destinations[ship.position]
            if (constants.MAX_TURNS -
                    game.turn_number) < 6 and ship.position in dropoffs:
                # ignore ship completely so that it can die
                ship.staying = True
            # should we build a drop-off?
            elif (len(ship_queue) >= SHIP_DO_RATIO * len(dropoffs)
                  and ship.position in do_spots
                  and game_map.calculate_distance(
                      ship.position, closest_dropoff(ship.position)) >
                  DO_DISTANCE and me.halite_amount > constants.DROPOFF_COST -
                  game_map[ship.position].halite_amount + ship.halite_amount
                  and game.turn_number < constants.MAX_TURNS * DO_TURN_FACTOR
                  and halite_percent > DO_HALITE_FACTOR and
                  # len(dropoffs) < 4 and
                  not dropoff):
                dropoff = True
                spent_so_far += constants.DROPOFF_COST - game_map[
                    ship.position].halite_amount
                command_queue.append(ship.make_dropoff())
                ship.staying = True
                positions_used.add(ship.position)
                d = ships_des.pop(ship.id, None)
                destinations.pop(d, None)
            # can it move?
            elif (game_map[ship.position].halite_amount *
                  (1 / constants.MOVE_COST_RATIO)) > ship.halite_amount:
                # can't move, stay put
                # logging.info(f'ship {ship.id} staying with {ship.halite_amount} avaliable')
                move(ship.position, ship.position, ship, positions_used,
                     command_queue)
                ship.staying = True
            elif ((ship.halite_amount > RETURN_AMOUNT)
                  or (game_map.calculate_distance(
                      ship.position, closest_dropoff(ship.position)) + 6 >=
                      (constants.MAX_TURNS - game.turn_number))):
                returning.add(ship.id)
                ship.returning = True
            elif (ship.halite_amount + ship.collect_amount > 1000):
                # its not worth staying on the square, just go home
                ship.returning = True
                returning.add(ship.id)

        # mark enemy ships if we don't control more than half the ships on the board

        if len(ship_queue) < len(enemy_locations):
            for pos in enemy_locations:
                for d in Direction.get_all_cardinals():
                    location = game_map.normalize(pos.directional_offset(d))
                    if game_map.calculate_distance(location,
                                                   closest_dropoff(pos)) > 1:
                        positions_used.add(location)

        logging.info(enemy_locations)

        for ship in ship_queue:
            if ship.position in dropoffs:
                returning.discard(ship.id)
                ship.returning = False
            elif ship.id in returning and not ship.staying:
                # move to drop-off
                # logging.info('move to dropoff')
                ship.returning = True
                if constants.MAX_TURNS - game.turn_number <= 10:
                    collide = True
                else:
                    collide = False

                d = ships_des.pop(ship.id, None)
                destinations.pop(d, None)

                move(closest_dropoff(ship.position),
                     ship.position,
                     ship,
                     positions_used,
                     command_queue,
                     collide=collide,
                     shortest=True)

        for ship in ship_queue:
            if ship.returning or ship.staying:
                continue
            elif (ship.halite_amount + ship.collect_amount > RETURN_AMOUNT):
                # will staying make me cross over the line?
                ship.staying = True
                move(ship.position, ship.position, ship, positions_used,
                     command_queue)

            else:
                logging.info(f'd {destinations}')
                highest_so_far = ship.collect_amount * STAY_FACTOR
                best = ship.position
                if ship.id in ships_des:
                    p = ships_des[ship.id]  # where I was going
                    w = game_map[p].halite_amount / (
                        game_map.calculate_distance(ship.position, p) *
                        DISTANCE_FACTOR + 1)
                    if p in enemy_locations:
                        w *= ENEMY_FACTOR
                    if w > highest_so_far:
                        best = p
                else:
                    for p in highs:
                        # p = game_map.normalize(p)
                        if p in destinations:
                            continue
                        hal = game_map[p].halite_amount

                        if p in dropoffs:
                            hal = ship.halite_amount

                        weighted = hal / (game_map.calculate_distance(
                            ship.position, p) * DISTANCE_FACTOR + 1)
                        if weighted > highest_so_far:
                            best = p
                        if p in destinations and destinations[p] != ship.id:
                            # logging.info(f'nope on {p} for ship {ship.id}')
                            continue

                p = best
                logging.info(f'Ship {ship.id} moving to position {p}')

                if ship.id in ships_des:
                    if ships_des[ship.id] != p:
                        if ships_des[ship.id] in destinations:
                            del destinations[ships_des[ship.id]]
                        else:
                            logging.info(
                                f'Mismatch. Expected {ships_des[ship.id]} in {destinations}'
                            )
                ships_des[ship.id] = p
                destinations[p] = ship.id
                if p in dropoffs:
                    shortest = True
                else:
                    shortest = False
                move(p,
                     ship.position,
                     ship,
                     positions_used,
                     command_queue,
                     shortest=shortest)
                ''''''

        halite_collected = me.halite_amount + spent_so_far - 5000
        ship_turns = 0
        for id, turn in first_seen.items():
            ship_turns += game.turn_number - turn

        collection_per_turn.append(halite_collected)

        if game.turn_number < 20:
            avg_per_ship_per_turn = 2000
        else:
            # halite_diff = collection_per_turn[game.turn_number - 1] - \
            #               collection_per_turn[game.turn_number - 21]
            avg_per_ship_per_turn = halite_collected / ship_turns

        logging.info(
            f'turn {game.turn_number} has avg {avg_per_ship_per_turn}')

        # if (avg_per_ship_per_turn * turns_left >= 1400 and
        if ((avg_per_ship_per_turn * turns_left >= BUILD_FACTOR)
                and me.halite_amount >= constants.SHIP_COST and not dropoff
                and halite_percent > BUILD_HALITE_LIMIT
                and syp not in positions_used):
            spent_so_far += constants.SHIP_COST
            positions_used.add(syp)
            command_queue.append(me.shipyard.spawn())
            # Send your moves back to the game environment, ending this turn.
        logging.info(command_queue)
        game.end_turn(command_queue)
Esempio n. 24
0
for i in range(0, game.game_map.height):
    current_value = []
    for j in range(0, game.game_map.width):
        current_value.append(
            calculate_tile_value(Position(i, j), game.me.shipyard.position))
    tileValues.append(current_value)

while True:
    game.update_frame()

    me = game.me
    game_map = game.game_map

    command_queue = []

    direction_order = Direction.get_all_cardinals() + [Direction.Still]

    def _ship_needs_tile(ship):
        "Simply Writing out for clarity."
        if ship.id not in ship_states:
            return True
        if ship_states[ship.id] in [
                EXPLORING, DEPOSITING
        ] and ship.position == previous_positions[ship.id]:
            return True
        if ship_states[ship.id] == HARVESTING and game_map[
                ship.position].halite_amount <= 10:
            return True
        else:
            return False
Esempio n. 25
0
def run():
    global spent_so_far
    destinations = {}
    ships_des = {}

    while True:
        game.update_frame()
        # You extract player metadata and the updated map metadata here for convenience.
        me = game.me
        game_map = game.game_map

        turns_left = constants.MAX_TURNS - game.turn_number
        halite_left = get_halite_amount()
        halite_percent = halite_left / starting_halite_amount

        highs = []
        # spots = PriorityQueue()
        for x, y in itertools.product(range(game_map.width),
                                      range(game_map.height)):
            highs.append(Position(x, y))

        highs = sorted(highs,
                       key=lambda p: game_map[p].halite_amount,
                       reverse=True)[:150]
        positions_used = set()
        command_queue = []

        ship_queue = me.get_ships()
        for do in me.get_dropoffs():
            pos = do.position
            if pos not in dropoffs:
                dropoffs.append(pos)

        # top10 = [highs.get().position for _ in range(10)]
        # logging.info(top10)

        # sort ships by proximity to shipyard
        ship_queue = sorted(
            ship_queue,
            key=lambda s: game_map.calculate_distance(s.position, syp),
            reverse=True)
        # ship_queue = sorted(ship_queue, key=lambda s: s.id,
        #                     reverse=True)

        dropoff = False
        for ship in ship_queue:
            if ship.id not in first_seen:
                first_seen[ship.id] = game.turn_number
            ship.staying = False
            ship.returning = False
            if ship.position in destinations:
                del destinations[ship.position]
            if (constants.MAX_TURNS -
                    game.turn_number) < 4 and ship.position in dropoffs:
                # ignore ship completely so that it can die
                ship.staying = True
            # should we build a drop-off?
            elif (len(ship_queue) >= 10 * len(dropoffs)
                  and ship.position in highs and game_map.calculate_distance(
                      ship.position, closest_dropoff(ship.position)) > 15
                  and me.halite_amount > constants.DROPOFF_COST -
                  game_map[ship.position].halite_amount + ship.halite_amount
                  and game.turn_number < constants.MAX_TURNS * 0.75
                  and halite_percent > 0.4 and
                  # len(dropoffs) < 4 and
                  not dropoff):
                dropoff = True
                spent_so_far += constants.DROPOFF_COST - game_map[
                    ship.position].halite_amount
                command_queue.append(ship.make_dropoff())
                ship.staying = True
                positions_used.add(ship.position)
            # can it move?
            elif (game_map[ship.position].halite_amount *
                  0.1) > ship.halite_amount:
                # can't move, stay put
                # logging.info(f'ship {ship.id} staying with {ship.halite_amount} avaliable')
                move(ship.position, ship.position, ship, positions_used,
                     command_queue)
                ship.staying = True
            elif ((ship.halite_amount > RETURN_AMOUNT)
                  or (game_map.calculate_distance(
                      ship.position, closest_dropoff(ship.position)) + 4 >=
                      (constants.MAX_TURNS - game.turn_number))):
                returning.add(ship.id)
                ship.returning = True
            elif (ship.halite_amount +
                  (game_map[ship.position].halite_amount * 0.25) > 1000):
                # its not worth staying on the square, just go home
                ship.returning = True
                returning.add(ship.id)

        # mark enemy ships if we don't control more than half the ships on the board
        total_num_of_ships = 0
        for i in game.players:
            total_num_of_ships += len(game.players[i].get_ships())

        if len(ship_queue) < total_num_of_ships:
            for i in game.players:
                if i == game.my_id:
                    continue
                player = game.players[i]
                for ship in player.get_ships():
                    for d in Direction.get_all_cardinals() + [(0, 0)]:
                        location = game_map.normalize(
                            ship.position.directional_offset(d))
                        if game_map.calculate_distance(
                                location, closest_dropoff(ship.position)) <= 1:
                            pass
                        # elif (ship.halite_amount > 950 and
                        #         len(game.players[ship.owner].get_ships()) < len(ship_queue)):
                        # its fine to collide with a high halite ship and steal its halite
                        # pass
                        else:
                            positions_used.add(location)

        for ship in ship_queue:
            if ship.position in dropoffs:
                returning.discard(ship.id)
                ship.returning = False
            elif ship.id in returning and not ship.staying:
                # move to drop-off
                # logging.info('move to dropoff')
                ship.returning = True
                if constants.MAX_TURNS - game.turn_number <= 10:
                    collide = True
                else:
                    collide = False

                move(closest_dropoff(ship.position),
                     ship.position,
                     ship,
                     positions_used,
                     command_queue,
                     collide=collide,
                     shortest=True)

        for ship in ship_queue:
            if ship.returning or ship.staying:
                continue
            elif (ship.halite_amount +
                  (game_map[ship.position].halite_amount * 0.25) >
                  RETURN_AMOUNT):
                # will staying make me cross over the line?
                ship.staying = True
                move(ship.position, ship.position, ship, positions_used,
                     command_queue)

            else:
                logging.info(f'd {destinations}')

                highest_so_far = game_map[ship.position].halite_amount
                best = ship.position
                for p in highs:
                    # p = game_map.normalize(p)
                    if p in destinations:
                        continue
                    hal = game_map[p].halite_amount

                    if p in dropoffs:
                        hal = ship.halite_amount

                    weighted = hal / (
                        game_map.calculate_distance(ship.position, p) + 1)
                    if weighted > highest_so_far:
                        best = p
                    if p in destinations and destinations[p] != ship.id:
                        # logging.info(f'nope on {p} for ship {ship.id}')
                        continue

                p = best
                logging.info(f'Ship {ship.id} moving to position {p}')

                if ship.id in ships_des:
                    if ships_des[ship.id] != p:
                        if ships_des[ship.id] in destinations:
                            del destinations[ships_des[ship.id]]
                        else:
                            logging.info(
                                f'Mismatch. Expected {ships_des[ship.id]} in {destinations}'
                            )
                ships_des[ship.id] = p
                destinations[p] = ship.id
                # if p in dropoffs:
                #     p.
                move(p,
                     ship.position,
                     ship,
                     positions_used,
                     command_queue,
                     shortest=False)
                ''''''

        halite_collected = me.halite_amount + spent_so_far - 5000
        ship_turns = 0
        for id, turn in first_seen.items():
            ship_turns += game.turn_number - turn

        collection_per_turn.append(halite_collected)

        if game.turn_number < 20:
            avg_per_ship_per_turn = 2000
        else:
            # halite_diff = collection_per_turn[game.turn_number - 1] - \
            #               collection_per_turn[game.turn_number - 21]
            avg_per_ship_per_turn = halite_collected / ship_turns / 1.1

        logging.info(
            f'turn {game.turn_number} has avg {avg_per_ship_per_turn}')

        # if (avg_per_ship_per_turn * turns_left >= 1400 and
        if (((turns_left > 150 and not NEW_SPAWN) or
             (avg_per_ship_per_turn * turns_left >= 1800 and NEW_SPAWN))
                and me.halite_amount >= constants.SHIP_COST and not dropoff
                and halite_percent > 0.4 and syp not in positions_used):
            spent_so_far += constants.SHIP_COST
            command_queue.append(me.shipyard.spawn())

            # Send your moves back to the game environment, ending this turn.
        logging.info(command_queue)
        game.end_turn(command_queue)
Esempio n. 26
0
                ship.position, close_drop.position) * 20) + (
                    game.turn_number *
                    2) and game_map[ship.position].halite_amount > 600:
            command_queue.append(ship.stay_still())
        else:
            shipyard_dist = int(2 + game.turn_number // 150)  #**
            if game.turn_number == 100 and shipyard_dist == 3:
                shipyard_dist += 1

            dist = game_map.calculate_distance(ship.position,
                                               close_drop.position)
            if dist < shipyard_dist:
                rand_move = rand_move_num % 4  #random.randInt(0,3)rand_move_num%4
                if ship.position == close_drop.position:
                    # rand_move_num += random.randint(0,4)
                    dir = Direction.get_all_cardinals()[random.randint(0, 3)]
                    if game_map[ship.position.directional_offset(
                            dir)].is_occupied or game_map[
                                ship.position.directional_offset(
                                    dir)].has_structure:
                        dir = game_map.naive_navigate(
                            ship, ship.position.directional_offset(dir))
                    command_queue.append(ship.move(dir))
                else:
                    if game_map[ship.position].halite_amount > 700:
                        command_queue.append(ship.stay_still())
                    else:
                        dir = game_map.naive_navigate(ship,
                                                      close_drop.position)
                        orig_dir = dir
                        if dir == Direction.North:
Esempio n. 27
0
def getShipMove(ship, sy):
    cleanPlaces(targetArea)
    bestSpot = []
    best = 0
    amount = 700
    options = 0
    if ship.position == Shipyard:
        openSpot = False
        for i in Direction.get_all_cardinals():
            if (game_map[ship.position.directional_offset(i)].is_occupied ==
                    False):
                openSpot = True

        if openSpot == False:
            bestDir = Direction.North
            placepicked.append(ship.position.directional_offset(bestDir))
            command_queue.append(ship.move(bestDir))
            return 0

    #< constants.MAX_HALITE / 35
    if (game_map[ship.position].halite_amount <= 50 and
        (ship.halite_amount < amount)) or (Shipyard.__eq__(ship.position)):
        #print("WOOOOOOLK")
        for i in Direction.get_all_cardinals():
            if (game_map[ship.position.directional_offset(i)].is_occupied ==
                    False):
                bestSpot.append(game_map[ship.position.directional_offset(i)])
                options += 1
        for i in bestSpot:
            if (i.halite_amount >= best):
                #bestDir = game_map.naive_navigate(ship, i.position)
                best = i.halite_amount
                bestDir = game_map.get_unsafe_moves(ship.position,
                                                    i.position)[0]
        if best < 100:
            if len(targetArea) == 0:
                pos = []
                for i in Direction.get_all_cardinals():
                    found = False
                    if (game_map[ship.position.directional_offset(
                            i)].is_occupied == False
                            and game_map[ship.position.directional_offset(i)].
                            position.__ne__(game_map[me.shipyard].position)):
                        pos.append(i)
                        #bestDir = (i)
                        found = True
                bestDir = random.choice(pos)
                if found == False:
                    bestDir = (0, 0)
                placepicked.append(ship.position.directional_offset(bestDir))
                command_queue.append(ship.move(bestDir))
                return 0
            else:

                bestDir = Direction.convertStr(getClosestSpot(ship))
                if game_map[ship.position.directional_offset(
                        bestDir)].is_occupied == False and not game_map[
                            ship.position.directional_offset(
                                bestDir)].position in placepicked:
                    placepicked.append(
                        ship.position.directional_offset(bestDir))
                    command_queue.append(ship.move(bestDir))
                    return 0
                bestDir = (0, 0)

        place = game_map[ship.position.directional_offset((bestDir))].position
        inPicked = False
        for i in placepicked:
            if (i.__eq__(place)):
                inPicked = True
        if inPicked == False and game_map[ship.position.directional_offset(
                bestDir)].is_occupied == False:
            placepicked.append(ship.position.directional_offset(bestDir))
            command_queue.append((ship.move(bestDir)))
            return 0
        else:
            isFound = False
            bestDir = (0, 0)
            for i in Direction.get_all_cardinals():
                if (game_map[ship.position.directional_offset(i)].is_occupied
                        == False) and ((game_map[
                            ship.position.directional_offset(i)].position
                                        in placepicked) == False):
                    bestDir = (game_map.get_unsafe_moves(
                        ship.position, ship.position.directional_offset(i))[0])
                    isFound = True
                    placepicked.append(
                        ship.position.directional_offset(bestDir))
                    command_queue.append(ship.move(bestDir))
                    return 0

            if isFound == False:
                command_queue.append(ship.stay_still())
                placepicked.append(ship.position)
                return 0

        #returnCommand = (ship.move(bestDir))
    else:
        if ship.is_full or ship.halite_amount > amount:
            #command_queue.append(game_map.get_unsafe_moves(ship.position, Shipyard)[0])
            placeVal = game_map[ship.position.directional_offset(
                game_map.get_unsafe_moves(ship.position,
                                          Shipyard)[0])].position
            inPicked = False
            for e in placepicked:
                if (placeVal.__eq__(e)):
                    inPicked = True

            if inPicked == True:
                isFound = False
                bestDir = (0, 0)
                for i in Direction.get_all_cardinals():
                    if (game_map[ship.position.directional_offset(
                            i)].is_occupied == False) and (
                                (game_map[ship.position.directional_offset(
                                    i)].position in placepicked) == False):
                        bestDir = (game_map.get_unsafe_moves(
                            ship.position,
                            ship.position.directional_offset(i))[0])
                        isFound = True
                        placepicked.append(
                            ship.position.directional_offset(bestDir))
                        command_queue.append(ship.move(bestDir))
                        return 0

                ##command_queue.append(ship.stay_still())
                ##placepicked.append(ship.position)
                ##return 0

            else:
                command_queue.append(
                    ship.move(game_map.naive_navigate(ship, Shipyard)))
                placepicked.append(placeVal)
                return 0

        else:
            if game_map[ship.position].halite_amount > 0:
                command_queue.append(ship.stay_still())
                placepicked.append(ship.position)
                return 0
            else:
                isFound = False
                bestDir = (0, 0)
                for i in Direction.get_all_cardinals():
                    if (game_map[ship.position.directional_offset(
                            i)].is_occupied == False) and (
                                (game_map[ship.position.directional_offset(
                                    i)].position in placepicked) == False):
                        bestDir = (game_map.get_unsafe_moves(
                            ship.position,
                            ship.position.directional_offset(i))[0])
                        isFound = True
                placepicked.append(ship.position.directional_offset(bestDir))
                command_queue.append(ship.move(bestDir))
                return 0
Esempio n. 28
0
    def run(self):
        """ <<<Game Begin>>> """

        # This game object contains the initial game state.
        # game = hlt.Game()
        game = self.game

        # Give ships extra time to make it back to a dock, may not be necessary with drop offs in place now
        TURN_REMAINING_FUDGE = 6
        # Don't go back out if the game is over, sit and get crashed
        # TURN_NO_NEW_ORDERS = 16
        # Build new ships until this turn
        BUILD_UNTIL = 200
        # Maximum number of drop offs to build
        MAX_DROPOFF = 2
        # Drop offs must be built at least this far from any other dock
        MIN_DIST_TO_DOCK = 16
        # width and height of a square used to find halite clusters
        CLUSTER_SIZE = 2
        # width and height of the game map
        MAP_SIZE = game.game_map.width
        # maximum number of turns in this game
        MAX_TURNS = 400
        # the number of players in the game
        NUM_PLAYERS = len(game.players)
        # which job is assigned to this ship
        SHIP_JOBS = {}
        # which position this ship is trying to reach
        SHIP_ORDERS = {}
        # amount of halite to return with
        RETURN_WITH = 900

        # todo: tune the following params

        # distance at which a ship counts towards NEAREST_SHIP_COUNT
        NEAREST_SHIP_DIST = 10
        # number of ships that must be nearby to consider making a dock
        NEAREST_SHIP_COUNT = 5
        # amount of halite gained required to move to a new tile
        REQUIRED_GAIN = 1.4
        # amount of gain required during CLEAN before switching to CLUSTER
        BEST_GAIN_THRESHOLD = 5
        # todo: determine if this param is valuable, block tiles near enemy ships in 4p games
        ENEMY_RADIUS = 0

        # set default params per map size
        if MAP_SIZE == 40:
            MAX_TURNS = 425
            BUILD_UNTIL = 225
            MAX_DROPOFF = 2
            # MIN_DIST_TO_DOCK = 18
            # TURN_REMAINING_FUDGE = 6
            # TURN_NO_NEW_ORDERS = 14
            CLUSTER_SIZE = 2
        elif MAP_SIZE == 48:
            MAX_TURNS = 450
            BUILD_UNTIL = 250
            MAX_DROPOFF = 3
            # MIN_DIST_TO_DOCK = 20
            # TURN_REMAINING_FUDGE = 6
            # TURN_NO_NEW_ORDERS = 10
            CLUSTER_SIZE = 2
        elif MAP_SIZE == 56:
            MAX_TURNS = 475
            BUILD_UNTIL = 275
            MAX_DROPOFF = 4
            # MIN_DIST_TO_DOCK = 22
            # TURN_REMAINING_FUDGE = 6
            # TURN_NO_NEW_ORDERS = 8
            CLUSTER_SIZE = 2
        elif MAP_SIZE == 64:
            MAX_TURNS = 500
            BUILD_UNTIL = 300
            MAX_DROPOFF = 6
            # MIN_DIST_TO_DOCK = 24
            # TURN_REMAINING_FUDGE = 6
            # TURN_NO_NEW_ORDERS = 6
            CLUSTER_SIZE = 2

        # update params based on the number of players
        if NUM_PLAYERS > 2:
            MAX_DROPOFF -= 1
            ENEMY_RADIUS = 1

        # calculate clusters
        cluster_values_o = [[0 for x in range(MAP_SIZE)]
                            for y in range(MAP_SIZE)]
        for x in range(MAP_SIZE):
            for y in range(MAP_SIZE):
                for y1 in range(y - CLUSTER_SIZE, y + CLUSTER_SIZE):
                    for x1 in range(x - CLUSTER_SIZE, x + CLUSTER_SIZE):
                        cluster_values_o[y][x] += game.game_map[Position(
                            x1, y1)].halite_amount

        cluster_avg_o = np.matrix(cluster_values_o).mean()
        cluster_std_o = np.matrix(cluster_values_o).std()

        game.ready("v19-2p")
        """ <<<Game Loop>>> """

        while True:
            game.update_frame()
            game_map = game.game_map
            me = game.me
            halite_available = me.halite_amount
            command_queue = []
            ship_moves = {}

            # Keep up with how many turns are left
            turns_remaining = MAX_TURNS - game.turn_number
            logging.info("turns remaining {}".format(turns_remaining))

            # calculate current cluster values
            cluster_values_n = [[0 for x in range(MAP_SIZE)]
                                for y in range(MAP_SIZE)]
            tile_values_n = [[0 for x in range(MAP_SIZE)]
                             for y in range(MAP_SIZE)]
            for x in range(MAP_SIZE):
                for y in range(MAP_SIZE):
                    tile_values_n[y][x] = game.game_map[Position(
                        x, y)].halite_amount
                    for y1 in range(y - CLUSTER_SIZE, y + CLUSTER_SIZE):
                        for x1 in range(x - CLUSTER_SIZE, x + CLUSTER_SIZE):
                            cluster_values_n[y][x] += game.game_map[Position(
                                x1, y1)].halite_amount

            cluster_avg_n = np.matrix(cluster_values_n).mean()
            cluster_std_n = np.matrix(cluster_values_n).std()
            cluster_threshold = cluster_avg_n + (cluster_std_n * .5)

            tiles_avg_n = np.matrix(tile_values_n).mean()
            tiles_std_n = np.matrix(tile_values_n).std()

            # dropoff calculations
            dropoffs = me.get_dropoffs()
            dropoff_p1 = halite_available > constants.DROPOFF_COST and len(
                dropoffs) < MAX_DROPOFF
            dropoff_built = False

            # calculate blocked/dangerous tiles
            # permanently blocked cells - enemy shipyards, update with enemy docks as game progresses
            blocked_tiles_n = [[False for x in range(MAP_SIZE)]
                               for y in range(MAP_SIZE)]
            danger_tiles_n = [[0 for x in range(MAP_SIZE)]
                              for y in range(MAP_SIZE)]
            for player in game.players.values():
                if player.id == game.me.id:
                    continue

                blocked = player.shipyard.position

                blocked_tiles_n[blocked.y][blocked.x] = True

            for player in game.players.values():
                if player.id == me.id:
                    continue

                for ship in player.get_ships():
                    blocked_tiles_n[ship.position.y][ship.position.x] = True

                    # in 4p games, consider all tiles around enemies dangerous
                    if ENEMY_RADIUS > 0:
                        for p_blocked in ship.position.get_surrounding_cardinals(
                        ):
                            p_norm = game_map.normalize(p_blocked)
                            danger_tiles_n[p_norm.y][p_norm.x] += 1

                for dropoff in player.get_dropoffs():
                    blocked_tiles_n[dropoff.position.y][
                        dropoff.position.x] = True

                    # always consider the tiles around a dropoff extremely dangerous
                    for x in range(dropoff.position.x - 1,
                                   dropoff.position.x + 1):
                        for y in range(dropoff.position.y - 1,
                                       dropoff.position.y + 1):
                            p_norm = game_map.normalize(Position(x, y))
                            danger_tiles_n[p_norm.y][p_norm.x] += 4
                            # blocked_tiles_n[p_norm.y][p_norm.x] = True

            # clear my shipyard
            blocked_tiles_n[me.shipyard.position.y][
                me.shipyard.position.x] = False

            # clear my dropoffs
            for dropoff in dropoffs:
                blocked_tiles_n[dropoff.position.y][dropoff.position.x] = False

            # iterate through my ships and block their locations
            # this is done outside of the all players loop so that I ignore enemy ships in my docks
            for ship in me.get_ships():
                blocked_tiles_n[ship.position.y][ship.position.x] = True

            # clean up ship orders by removing orders tied to ships that have been lost
            orders_to_clear = []
            for key in SHIP_ORDERS.keys():
                try:
                    if me.get_ship(key) is None:
                        orders_to_clear.append(key)
                except KeyError:
                    orders_to_clear.append(key)

            for key in orders_to_clear:
                del SHIP_ORDERS[key]

            # iterate through my ships and give them orders
            for ship in me.get_ships():
                logging.info("Ship {} at position {} has {} halite.".format(
                    ship.id, ship.position, ship.halite_amount))
                logging.info("Ship {} job {} target {}".format(
                    ship.id, SHIP_JOBS.get(ship.id), SHIP_ORDERS.get(ship.id)))

                # find closest dock, starting with shipyard
                closest_dock = me.shipyard
                distance_to_dock = game_map.calculate_distance(
                    ship.position, me.shipyard.position)

                # assign default job to new ships and order them out of the shipyard
                if SHIP_JOBS.get(ship.id) is None or distance_to_dock == 0:
                    SHIP_JOBS[ship.id] = "CLEAN"
                    unsafe_moves = Direction.get_all_cardinals()
                    logging.info("Ship {} needs to gtfo of the dock".format(
                        ship.id, len(unsafe_moves)))
                    logging.info("Ship {} submitted {} potential moves".format(
                        ship.id, len(unsafe_moves)))
                    ship_moves[ship.id] = unsafe_moves

                    # on to the next ship
                    continue

                # check for closer dropoff
                for dropoff in dropoffs:
                    new_dist = game_map.calculate_distance(
                        ship.position, dropoff.position)
                    if new_dist < distance_to_dock:
                        distance_to_dock = new_dist
                        closest_dock = dropoff

                logging.info("Ship {} closest_dock {} distance {}".format(
                    ship.id, closest_dock, distance_to_dock))

                # determine if this ship should convert to a dropoff
                if dropoff_p1 and not dropoff_built and distance_to_dock > MIN_DIST_TO_DOCK:
                    logging.info(
                        'todo: determine if ship should become dropoff')
                    dropoff_p2 = False
                    dropoff_p3 = False

                    # evaluate cluster value at ship position
                    if cluster_values_n[ship.position.y][
                            ship.position.x] > cluster_threshold:
                        dropoff_p2 = True

                    if dropoff_p2:
                        nearby_ships = []

                        for ship_a in me.get_ships():
                            # ignore this ship
                            if ship_a.id == ship.id:
                                continue

                            if game_map.calculate_distance(
                                    ship_a.position,
                                    ship.position) < NEAREST_SHIP_DIST:
                                nearby_ships.append(ship_a)

                            if len(nearby_ships) > NEAREST_SHIP_COUNT:
                                dropoff_p3 = True
                                break

                        if dropoff_p3:
                            logging.info('should become dropoff')
                            dropoff_built = True
                            halite_available -= constants.DROPOFF_COST
                            command_queue.append(ship.make_dropoff())
                            blocked_tiles_n[ship.position.y][
                                ship.position.x] = False

                            # move on to next ship
                            continue

                # start heading home if the game is almost over
                if turns_remaining - TURN_REMAINING_FUDGE <= distance_to_dock:
                    logging.info("Ship {} converted to {}".format(
                        ship.id, 'CRASH'))
                    SHIP_JOBS[ship.id] = "CRASH"

                # Job == CRASH
                if SHIP_JOBS.get(ship.id) == "CRASH":
                    logging.info("Ship {} job {}".format(ship.id, 'CRASH'))

                    # do nothing, game is almost over
                    if distance_to_dock == 0:
                        logging.info("Ship {} waiting for the end".format(
                            ship.id, 'RETURN'))

                        continue

                    # get moves that will move this ship towards the closest dock
                    unsafe_moves = game_map.get_unsafe_moves(
                        ship.position, closest_dock.position)

                    # move into dock, ignoring collisions
                    if distance_to_dock == 1:
                        logging.info("Ship {} crashing dock {}".format(
                            ship.id, closest_dock))

                        for move in unsafe_moves:
                            command_queue.append(ship.move(move))
                            blocked_tiles_n[ship.position.y][
                                ship.position.x] = False

                            break

                        # next ship
                        continue
                    else:
                        logging.info(
                            "Ship {} submitted {} potential moves".format(
                                ship.id, len(unsafe_moves)))
                        ship_moves[ship.id] = unsafe_moves

                # return home if carrying a lot of halite
                if ship.halite_amount > RETURN_WITH:
                    SHIP_JOBS[ship.id] = "RETURN"

                # JOB == RETURN
                if SHIP_JOBS.get(ship.id) == "RETURN":
                    logging.info("Ship {} job {}".format(ship.id, 'RETURN'))

                    # in the dock already
                    if distance_to_dock == 0:
                        # game almost over
                        if "CRASH" in SHIP_JOBS.values():
                            logging.info("Ship {} waiting for the end".format(
                                ship.id))

                            # todo: make sure I don't need to mark this as free

                            # wait to be destroyed
                            continue

                        # assign new job
                        logging.info("Ship {} assigned job {}".format(
                            ship.id, "CLEAN"))
                        SHIP_JOBS[ship.id] = "CLEAN"

                        # get out of the dock
                        # del SHIP_JOBS[ship.id]
                        # unsafe_moves = Direction.get_all_cardinals()
                        # logging.info("Ship {} needs to gtfo of the dock".format(ship.id, len(unsafe_moves)))
                        # logging.info("Ship {} submitted {} potential moves".format(ship.id, len(unsafe_moves)))
                        # ship_moves[ship.id] = unsafe_moves
                    elif distance_to_dock == 1:
                        if "CRASH" in SHIP_JOBS.values():
                            logging.info("Ship {} crashing dock {}".format(
                                ship.id, closest_dock))

                            unsafe_moves = game_map.get_unsafe_moves(
                                ship.position, closest_dock.position)
                            for move in unsafe_moves:
                                command_queue.append(ship.move(move))
                                blocked_tiles_n[ship.position.y][
                                    ship.position.x] = False

                                break

                            # move to next ship
                            continue
                        else:
                            unsafe_moves = game_map.get_unsafe_moves(
                                ship.position, closest_dock.position)
                            logging.info(
                                "Ship {} submitted {} potential moves".format(
                                    ship.id, len(unsafe_moves)))
                            ship_moves[ship.id] = unsafe_moves
                    else:
                        logging.info("Ship {} heading to dock {}".format(
                            ship.id, closest_dock))
                        unsafe_moves = game_map.get_unsafe_moves(
                            ship.position, closest_dock.position)
                        logging.info(
                            "Ship {} submitted {} potential moves".format(
                                ship.id, len(unsafe_moves)))
                        ship_moves[ship.id] = unsafe_moves

                # JOB == CLEAN
                if SHIP_JOBS.get(ship.id) == "CLEAN":
                    logging.info("Ship {} job {}".format(ship.id, 'CLEAN'))

                    cur_pos_val = game_map[ship.position].halite_amount
                    cur_pos_gain = math.ceil(cur_pos_val * .25)
                    cur_pos_val_next = cur_pos_val - cur_pos_gain
                    cost_to_move = math.floor(cur_pos_val / 10)
                    nearby_positions = ship.position.get_surrounding_cardinals(
                    )
                    best_gain = cur_pos_gain
                    best_position = ship.position
                    min_gain = cur_pos_gain * REQUIRED_GAIN
                    ranked_positions = {}

                    for position in nearby_positions:
                        p_norm = game_map.normalize(position)

                        logging.info("Ship {} considering {}.".format(
                            ship.id, p_norm))

                        # ignore closest dock
                        if p_norm == closest_dock.position:
                            continue

                        tile_value = game_map[p_norm].halite_amount
                        potential_gain = math.ceil(
                            tile_value * .25) - cost_to_move

                        logging.info(
                            "Ship {} considering {} halite {}.".format(
                                ship.id, p_norm, tile_value))

                        if min_gain < potential_gain:
                            logging.info(
                                "Ship {} considering {} potential_gain {}.".
                                format(ship.id, p_norm, potential_gain))
                            ranked_positions[potential_gain] = p_norm

                            if potential_gain > best_gain:
                                best_position = p_norm
                                best_gain = potential_gain

                        # todo: confirm this works, sometimes we might be better off sitting still

                    if best_gain < BEST_GAIN_THRESHOLD:
                        logging.info("Ship {} assigned job {}".format(
                            ship.id, "CLUSTER"))
                        SHIP_JOBS[ship.id] = "CLUSTER"
                    elif best_gain == cur_pos_gain:
                        logging.info("Ship {} {}".format(
                            ship.id, "staying still"))
                    else:
                        # order positions and append to requested moves
                        unsafe_moves = []
                        for k in sorted(ranked_positions.keys(), reverse=True):
                            unsafe_moves += game_map.get_unsafe_moves(
                                ship.position, ranked_positions[k])

                        logging.info(
                            "Ship {} submitted {} potential moves".format(
                                ship.id, len(unsafe_moves)))
                        ship_moves[ship.id] = unsafe_moves

                # JOB == CLUSTER
                if SHIP_JOBS.get(ship.id) == "CLUSTER":
                    logging.info("Ship {} job {}".format(ship.id, 'CLUSTER'))
                    needs_assignment = True

                    # validate existing order
                    if SHIP_ORDERS.get(ship.id):
                        order = SHIP_ORDERS.get(ship.id)
                        logging.info(
                            "Ship {} has existing assignment {}".format(
                                ship.id, order))

                        # if ship at target, clean, else determine if target is still valid
                        if game_map.calculate_distance(ship.position,
                                                       order) == 0:
                            logging.info("Ship {} reached target {}".format(
                                ship.id, order))
                            logging.info("Ship {} {}".format(
                                ship.id, "staying still"))
                            logging.info("Ship {} assigned job {}".format(
                                ship.id, "CLEAN"))

                            del SHIP_ORDERS[ship.id]
                            SHIP_JOBS[ship.id] = "CLEAN"
                            needs_assignment = False
                        else:
                            logging.info(
                                "Ship {} has not reached target {}".format(
                                    ship.id, order))
                            cluster_ratio = cluster_values_n[order.y][
                                order.x] / cluster_values_o[order.y][order.x]
                            if cluster_ratio < .6:
                                # todo: this might not work towards the end of a game with high performance bots
                                logging.info(
                                    "Ship {} target {} remaining {} - new target"
                                    .format(ship.id, order, cluster_ratio))
                            elif game_map[order].is_occupied:
                                logging.info(
                                    "Ship {} target {} occupied - new target".
                                    format(ship.id, order))
                            else:
                                needs_assignment = False
                                logging.info(
                                    'Ship {} continuing towards {}'.format(
                                        ship.id, order))
                                unsafe_moves = game_map.get_unsafe_moves(
                                    ship.position, order)
                                logging.info(
                                    "Ship {} submitted {} potential moves".
                                    format(ship.id, len(unsafe_moves)))
                                ship_moves[ship.id] = unsafe_moves

                    if needs_assignment:
                        logging.info("Ship {} {}".format(
                            ship.id, 'getting new assignment'))

                        clusters = {}
                        for x in range(MAP_SIZE):
                            for y in range(MAP_SIZE):
                                cluster_value = cluster_values_n[y][x]
                                if cluster_value > cluster_threshold:
                                    cluster_position = Position(x, y)
                                    cluster_distance = game_map.calculate_distance(
                                        ship.position, cluster_position)

                                    if cluster_distance == 0:
                                        cluster_distance = 1
                                    else:
                                        cluster_distance = cluster_distance * cluster_distance

                                    clusters[
                                        cluster_value /
                                        cluster_distance] = cluster_position

                        if len(clusters.keys()) > 0:
                            best_position = None

                            for cluster in sorted(clusters.keys(),
                                                  reverse=True):
                                logging.info(
                                    'Ship {} testing Position {} value {}'.
                                    format(ship.id, clusters[cluster],
                                           cluster))

                                if game_map[clusters[cluster]].is_occupied:
                                    logging.info(
                                        'Ship {} Position {} is occupied'.
                                        format(ship.id, clusters[cluster]))
                                    continue

                                if clusters[cluster] in SHIP_ORDERS.values():
                                    logging.info(
                                        'Ship {} Position {} is already assigned'
                                        .format(ship.id, clusters[cluster]))
                                    continue

                                # determine if there are too many ships close to this cluster already
                                x = clusters[cluster].x
                                y = clusters[cluster].y
                                ships_in_cluster = 0
                                for y1 in range(y - CLUSTER_SIZE,
                                                y + CLUSTER_SIZE):
                                    for x1 in range(x - CLUSTER_SIZE,
                                                    x + CLUSTER_SIZE):
                                        if game_map[Position(x1,
                                                             y1)].is_occupied:
                                            ships_in_cluster += 1

                                # todo: validate this number is relevant
                                if ships_in_cluster > 10:
                                    continue

                                # todo: determine if this ship can move towards cluster

                                best_position = clusters[cluster]
                                SHIP_ORDERS[ship.id] = best_position
                                break

                            if best_position:
                                logging.info(
                                    'Ship {} targeting best cluster {}'.format(
                                        ship.id, best_position))
                                unsafe_moves = game_map.get_unsafe_moves(
                                    ship.position, best_position)
                                logging.info(
                                    "Ship {} submitted {} potential moves".
                                    format(ship.id, len(unsafe_moves)))
                                ship_moves[ship.id] = unsafe_moves

            # attempt to solve traffic jams
            changes_made = True
            while changes_made:
                if len(ship_moves.keys()) == 0:
                    break

                changes_made = False
                ship_ids_resolved = []

                for k in ship_moves.keys():
                    ship = me.get_ship(k)
                    unsafe_moves = ship_moves[k]

                    # if ship does not have enough halite to move, mark it resolved
                    cur_pos_val = game_map[ship.position].halite_amount
                    cost_to_move = math.floor(cur_pos_val / 10)

                    if ship.halite_amount < cost_to_move:
                        logging.info('Ship {} cannot move'.format(ship.id))
                        ship_ids_resolved.append(k)
                        continue

                    for move in unsafe_moves:
                        potential_position = game_map.normalize(
                            ship.position.directional_offset(move))
                        logging.info("Ship {} testing {}".format(
                            ship.id, potential_position))

                        # tile is blocked
                        if blocked_tiles_n[potential_position.y][
                                potential_position.x]:
                            logging.info(
                                "Ship {} testing {} is blocked".format(
                                    ship.id, potential_position))
                            logging.info("{} occupied {}".format(
                                potential_position,
                                game_map[potential_position].is_occupied))
                            continue

                        # tile is dangerous
                        if ENEMY_RADIUS > 0 and SHIP_JOBS.get(
                                ship.id) == "CLEAN":
                            danger_rating = danger_tiles_n[
                                potential_position.y][potential_position.x]

                            # ignore dangerous tiles
                            if danger_rating > 3:
                                logging.info("{} danger {}".format(
                                    potential_position, danger_rating))
                                continue

                            # todo: test danger ratio of tile if job is clean
                            if danger_rating > 0 and tile_values_n[
                                    potential_position.y][
                                        potential_position.x] < tiles_avg_n + (
                                            tiles_std_n * danger_rating):
                                continue

                        logging.info('Ship {} moving to {}'.format(
                            ship.id, potential_position))
                        command_queue.append(ship.move(move))
                        blocked_tiles_n[ship.position.y][
                            ship.position.x] = False
                        blocked_tiles_n[potential_position.y][
                            potential_position.x] = True
                        changes_made = True
                        ship_ids_resolved.append(k)
                        break

                # clear out resolved moves
                if len(ship_ids_resolved) > 0:
                    logging.info('Resolved {} ships'.format(
                        len(ship_ids_resolved)))
                    for ship_id in ship_ids_resolved:
                        del ship_moves[ship_id]

            # ships could not move due to blocked tiles, attempt to swap
            if len(ship_moves.keys()) > 0:
                logging.info("{} ships did not move, attempting swaps".format(
                    len(ship_moves.keys())))

                changes_made = True
                while changes_made:
                    if len(ship_moves.keys()) == 0:
                        break

                    changes_made = False
                    ship_ids_resolved = []

                    for k in ship_moves.keys():
                        for k1 in ship_moves.keys():
                            if k == k1:
                                continue

                            ship_a = me.get_ship(k)
                            ship_b = me.get_ship(k1)

                            if game_map.calculate_distance(
                                    ship_a.position, ship_b.position) > 1:
                                continue

                            positions_a = []
                            moves_a = ship_moves[k]
                            for move in moves_a:
                                positions_a.append(
                                    game_map.normalize(
                                        ship_a.position.directional_offset(
                                            move)))

                            positions_b = []
                            moves_b = ship_moves[k1]
                            for move in moves_b:
                                positions_b.append(
                                    game_map.normalize(
                                        ship_b.position.directional_offset(
                                            move)))

                            if ship_a.position in positions_b and ship_b.position in positions_a:
                                logging.info(
                                    "ship {} at {} can swap with ship {} at {}"
                                    .format(k, ship_a.position, k1,
                                            ship_b.position))

                                unsafe_a = game_map.get_unsafe_moves(
                                    ship_a.position, ship_b.position)
                                unsafe_b = game_map.get_unsafe_moves(
                                    ship_b.position, ship_a.position)

                                command_queue.append(ship_a.move(unsafe_a[0]))
                                command_queue.append(ship_b.move(unsafe_b[0]))

                                changes_made = True
                                ship_ids_resolved.append(k)
                                ship_ids_resolved.append(k1)
                                break

                        if changes_made:
                            # ship a and b swapped, neither one is valid anymore and they need to be cleaned up
                            break

                    # clear out resolved moves
                    if len(ship_ids_resolved) > 0:
                        logging.info("Swapping resolved {} ships".format(
                            len(ship_ids_resolved)))
                        for ship_id in ship_ids_resolved:
                            del ship_moves[ship_id]

            logging.info("{} ships did not move".format(len(
                ship_moves.keys())))

            # spawn ships
            if game.turn_number <= BUILD_UNTIL and halite_available >= constants.SHIP_COST and not \
                    blocked_tiles_n[me.shipyard.position.y][me.shipyard.position.x]:
                command_queue.append(me.shipyard.spawn())
                halite_available -= constants.SHIP_COST

            # Send your moves back to the game environment, ending this turn.
            game.end_turn(command_queue)
Esempio n. 29
0
def run():
    global spent_so_far
    while True:
        game.update_frame()
        # You extract player metadata and the updated map metadata here for convenience.
        me = game.me
        game_map = game.game_map

        turns_left = constants.MAX_TURNS - game.turn_number
        halite_left = get_halite_amount()
        halite_percent = halite_left / starting_halite_amount

        # highs = PriorityQueue()
        # spots = PriorityQueue()
        # for x, y in itertools.product(range(game_map.width), range(game_map.height)):
        #     highs.put(
        #         PP(
        #             (constants.MAX_HALITE - game_map[Position(x, y)].halite_amount * .25) +
        #                 (game_map.calculate_distance(Position(x,y),(0, 0) syp)) * 2,
        #             Position(x, y)))

        positions_used = set()
        destinations = set()
        command_queue = []

        ship_queue = me.get_ships()
        for do in me.get_dropoffs():
            pos = do.position
            if pos not in dropoffs:
                dropoffs.append(pos)

        # top10 = [highs.get().position for _ in range(10)]
        # logging.info(top10)

        # sort ships by proximity to shipyard
        # ship_queue = sorted(ship_queue, key=lambda s: game_map.calculate_distance(s.position, syp),
        #                     reverse=True)
        ship_queue = sorted(ship_queue, key=lambda s: s.id, reverse=True)

        dropoff = False
        for ship in ship_queue:
            if ship.id not in first_seen:
                first_seen[ship.id] = game.turn_number
            ship.staying = False
            ship.returning = False
            if ship.position in destinations:
                destinations.remove(ship.position)
            if (constants.MAX_TURNS -
                    game.turn_number) < 4 and ship.position in dropoffs:
                # ignore ship completely so that it can die
                ship.staying = True
            # should we build a drop-off?
            elif (len(ship_queue) > 12 * len(dropoffs)
                  and game_map.calculate_distance(
                      ship.position, closest_dropoff(ship.position)) > 15
                  and me.halite_amount > constants.DROPOFF_COST -
                  game_map[ship.position].halite_amount + ship.halite_amount
                  and game.turn_number < constants.MAX_TURNS * 0.75
                  and halite_percent > 0.4 and
                  # len(dropoffs) < 4 and
                  not dropoff):
                dropoff = True
                spent_so_far += constants.DROPOFF_COST - game_map[
                    ship.position].halite_amount
                command_queue.append(ship.make_dropoff())
                ship.staying = True
                positions_used.add(ship.position)
            # can it move?
            elif (game_map[ship.position].halite_amount *
                  0.1) > ship.halite_amount:
                # can't move, stay put
                # logging.info(f'ship {ship.id} staying with {ship.halite_amount} avaliable')
                move(ship.position, ship.position, ship, positions_used,
                     command_queue)
                ship.staying = True
            elif ((ship.halite_amount > 850)
                  or (game_map.calculate_distance(
                      ship.position, closest_dropoff(ship.position)) + 4 >=
                      (constants.MAX_TURNS - game.turn_number))):
                returning.add(ship.id)
                ship.returning = True
            elif (ship.halite_amount +
                  (game_map[ship.position].halite_amount * 0.25) > 1000):
                # its not worth staying on the square, just go home
                ship.returning = True
                returning.add(ship.id)

        # mark enemy ships if we don't control more than half the ships on the board
        total_num_of_ships = 0
        for i in game.players:
            total_num_of_ships += len(game.players[i].get_ships())

        if len(ship_queue) < total_num_of_ships:
            for i in game.players:
                if i == game.my_id:
                    continue
                player = game.players[i]
                for ship in player.get_ships():
                    for d in Direction.get_all_cardinals() + [(0, 0)]:
                        location = game_map.normalize(
                            ship.position.directional_offset(d))
                        if game_map.calculate_distance(
                                location, closest_dropoff(ship.position)) <= 1:
                            pass
                        # elif (ship.halite_amount > 950 and
                        #         len(game.players[ship.owner].get_ships()) < len(ship_queue)):
                        # its fine to collide with a high halite ship and steal its halite
                        # pass
                        else:
                            positions_used.add(location)

        for ship in ship_queue:
            if ship.position in dropoffs:
                returning.discard(ship.id)
                ship.returning = False
            elif ship.id in returning and not ship.staying:
                # move to drop-off
                # logging.info('move to dropoff')
                ship.returning = True
                if constants.MAX_TURNS - game.turn_number <= 10:
                    collide = True
                else:
                    collide = False

                move(closest_dropoff(ship.position),
                     ship.position,
                     ship,
                     positions_used,
                     command_queue,
                     collide=collide,
                     shortest=True)

        for ship in ship_queue:
            if ship.returning or ship.staying:
                continue
            elif ((ship.halite_amount +
                   (game_map[ship.position].halite_amount * 0.25) > 850)):  #or
                # game_map[ship.position].halite_amount > constants.MAX_HALITE / 14):
                # will staying make me cross over the line?
                ship.staying = True
                move(ship.position, ship.position, ship, positions_used,
                     command_queue)

            # ships_left = [ship for ship in ship_queue if not ship.staying and not ship.returning]
            # if ships_left:
            #     ps = PriorityQueue()
            #     """a = np.array([(x,y) for x,y in itertools.product(range(ship.position.x-25, ship.position.x+25),
            #                                    range(ship.position.y-25, ship.position.y+25))])
            #
            #     """
            #     for x, y in itertools.product(range(game_map.height), range(game_map.width)):
            #         p = Position(x, y)
            #         if p in dropoffs:distance_array = np.array([[abs(i) + abs(j) for i in range(-20, 21)] for j in range(-20, 21)])
            #             continue
            #
            #         # result = abs(p - closest_dropoff(p))
            #         # a = min(result.x, game_map.width - result.x)
            #         # b = min(result.y, game_map.height - result.y)
            #         # priority = (game_map[p].halite_amount /
            #         #             (math.sqrt(a ** 2 + b ** 2) / 2))
            #         priority = (game_map[p].halite_amount /
            #                     (game_map.calculate_distance(p, closest_dropoff(p)) / 3))
            #         ps.put(PP(- priority, p))
            #
            #     while True:
            #         if ps.empty():
            #             break
            #         # logging.info(f'ships left: {ships_left}')
            #         pp = ps.get()
            #         best_so_far = 10000
            #         current_best = 0
            #         # find closest ship
            #         for ship in ships_left:
            #             distance = game_map.calculate_distance(ship.position, pp.position)
            #             rate = - game_map[ship.position].halite_amount * 1.4
            #             if distance <= best_so_far:
            #                 if rate > pp.priority:
            #                     best_so_far = distance
            #                     current_best = ship
            #         ship = current_best
            #         if ship:
            #             move(pp.position, ship.position, ship, positions_used, command_queue,
            #                  shortest=False)
            #             ships_left.remove(ship)
            #
            #     # logging.info(f'ships left: {ships_left}')
            #     for ship in ships_left:
            #         # logging.info(f'ship left {ship}')
            #         move(ship.position, ship.position, ship, positions_used, command_queue)

            else:
                halite_grid = [[0] * 41] * 41
                for x, y in itertools.product(
                        range(ship.position.x - 20, ship.position.x + 21),
                        range(ship.position.y - 20, ship.position.y + 21)):
                    p = game_map.normalize(Position(x, y))
                    if p in destinations:
                        continue
                    cell = game_map[p]
                    hal = cell.halite_amount
                    best_so_far = 0
                    # if p == ship.position:
                    #     continue
                    # if p in dropoffs:
                    # Gravity for the dropoff is equivalent to halite in ship
                    # hal = ship.halite_amount
                    # if cell.ship and cell.ship.owner != me.id:
                    #         hal -= 200
                    # p_val = (0.07 * hal /
                    #         (game_map.calculate_distance(ship.position, p) + 1) ** 2)
                    halite_grid[x - ship.position.x - 20][y - ship.position.y -
                                                          20] = hal
                    # p_val = (hal /
                    #          (game_map.calculate_distance(ship.position, p) + 1))
                    # if p_val > best_so_far:
                    #     best_so_far = p_val
                    #     current_best = p

                hal_ar = np.array(halite_grid)
                grav = hal_ar / distance_2
                # grav = grav / distance_array

                u = Direction.North, grav[:21, :]
                d = Direction.South, grav[20:, :]
                l = Direction.West, grav[:, :21]
                r = Direction.East, grav[:, 20:]

                moves = [(Direction.Still,
                          game_map[ship.position].halite_amount)]
                for dir, g in (u, d, l, r):
                    n = np.linalg.norm(g)
                    moves.append((dir, n))

                moves = sorted(moves, key=lambda x: x[1], reverse=True)
                logging.info(f'moves {moves}')
                for d, _ in moves:
                    p = ship.position.directional_offset(d)
                    if p not in positions_used:
                        if p in dropoffs:
                            # move to drop-off
                            shortest = True
                        else:
                            shortest = False
                        move(p,
                             ship.position,
                             ship,
                             positions_used,
                             command_queue,
                             shortest=shortest)
                        break
                else:
                    move(ship.position, ship.position, ship, positions_used,
                         command_queue)

                # logging.info(halite_grid)

                # p = ps.get().position
                # p = current_best

                # destinations.add(p)
                # move(p, ship.position, ship, positions_used, command_queue, shortest=shortest)
                ''''''

        halite_collected = me.halite_amount + spent_so_far - 5000
        ship_turns = 0
        for id, turn in first_seen.items():
            ship_turns += game.turn_number - turn

        collection_per_turn.append(halite_collected)

        if game.turn_number < 20:
            avg_per_ship_per_turn = 2000
        else:
            # halite_diff = collection_per_turn[game.turn_number - 1] - \
            #               collection_per_turn[game.turn_number - 21]
            avg_per_ship_per_turn = halite_collected / ship_turns / 1.2

        logging.info(
            f'turn {game.turn_number} has avg {avg_per_ship_per_turn}')

        # if (turns_left > 175 and        # Don't spawn a ship if you currently have a ship at port, though - the ships will collide.
        # if (avg_per_ship_per_turn * turns_left >= 1400 and
        if (((6 * turns_left > 1400 and not NEW_SPAWN) or
             (avg_per_ship_per_turn * turns_left >= 1800 and NEW_SPAWN))
                and me.halite_amount >= constants.SHIP_COST and not dropoff
                and halite_percent > 0.5 and syp not in positions_used):
            spent_so_far += constants.SHIP_COST
            command_queue.append(me.shipyard.spawn())

            # Send your moves back to the game environment, ending this turn.
        logging.info(command_queue)
        game.end_turn(command_queue)
Esempio n. 30
0
def calculate_real_distance(target,
                            source,
                            positions,
                            enemy_locations,
                            amount,
                            ship,
                            collide=False,
                            turn=0,
                            la=13):
    # if turn == 1:
    source = game.game_map.normalize(source)
    if turn == la:
        return 1, amount, [(0, 0)]

    if turn == 1:
        # logging.info(f'zz: {target}, {source}, {positions}, {amount}, {turn}')
        if collide and source in dropoffs:
            pass
        elif source in positions:
            return 100, -5, [(0, 0)]
        elif source in enemy_locations and amount > 100:
            enemy_ship = enemy_locations[source]
            if enemy_ship.halite_amount > 600:
                # ignore this ship
                pass
            else:
                return 30, -1, [(0, 0)]
        elif amount > 600:
            for d in Direction.get_all_cardinals():
                if game.game_map.normalize(
                        source.directional_offset(d)) in enemy_locations:
                    return 30, -1, [(0, 0)]

    if turn in (2, 3, 4):
        ship_id = claimed_moves[game.turn_number + 1].get(source)
        if ship_id and ship_id != ship.id:
            return 50, -2, [(0, 0)]

    if target == source and turn != 0:
        if turn == 0:
            logging.info('hit')
        return 1, amount, [(0, 0)]

    stay_moves = 0
    cost_of_move = game.game_map[source].halite_amount * 0.1
    if amount - int(cost_of_move) < 0:
        # must stay
        stay_moves += 1
        collected = math.ceil(game.game_map[source].halite_amount * 0.25)
        spot_new = game.game_map[source].halite_amount - collected
        amount = min(amount + collected, 1000) - int(spot_new * 0.1)
        stayed = True

    else:
        amount = amount - int(cost_of_move)
        stayed = False

    def calc_move(d, cur_best):
        new_pos = source.directional_offset(d)
        num_moves, new_amount, direcs = calculate_real_distance(
            target,
            new_pos,
            positions,
            enemy_locations,
            amount,
            ship,
            collide=collide,
            turn=turn + 1,
            la=la)

        if turn == 0 and ship.id == 14:
            logging.info(f'{num_moves} : {new_amount} : {direcs}')
        if d == (0, 0):
            collected = math.ceil(game.game_map[new_pos].halite_amount * 0.25)
            new_amount = min(new_amount + collected, 1000)
        # logging.info(f'target {target} to source {source}: {}')
        # if num_moves >= 80:
        #     return cur_best

        # if (num_moves < cur_best[0] or
        #         (num_moves == cur_best[0] and amount > cur_best[1])):
        if (new_amount > cur_best[1]) or (new_amount == cur_best[1]
                                          and num_moves < cur_best[0]):
            return num_moves, new_amount, [d] + direcs

        return cur_best

    # stay, up, right, left, down - bottom left
    # all_possible = {(0, 0),  (0, 1), (1, 0), (-1, 0), (0, -1)}
    # stay, left, right, down, up - upper right
    # all_possible = {(0, 0), (-1, 0), (1, 0), (0, -1), (0, 1)}
    # stay, right, left, up, down - bottom left
    # all_possible = {(0, 0), (1, 0), (-1, 0), (0, 1), (0, -1)}
    # stay, down, right, left, up - upper right
    # all_possible = {(0, 0), (0, -1), (1, 0), (-1, 0), (0, 1)}
    # stay, up, left, right, down - bottom left
    # all_possible = {(0, 0), (0, 1), (-1, 0), (0, 1), (0, -1)}
    # stay, up, left, down, right - bottom left
    all_possible = {
        (0, 1),
        (-1, 0),
        (0, -1),
        (1, 0),
        (0, 0),
    }
    # stay, down, left, up, right - bottom right
    # all_possible = {(0, 0), (0, -1), (-1, 0), (0, 1), (1, 0)}
    # all_possible = {(0,0), (0, -1), (1, 0), (-1, 0), (0, 1)}
    # if game.turn_number < 20:
    #     for dop in all_possible:
    #         logging.info(dop)
    ideal = set()
    medio = set()
    fallback = set()

    moves = game.game_map.get_unsafe_moves(source, target)
    if target == source:
        assert len(moves) == 0
        ideal.add((0, 0))
        all_possible.discard((0, 0))
        fallback = all_possible
    elif len(moves) == 1:
        # try move first
        direction = moves[0]
        ideal.add(direction)
        all_possible.discard(direction)

        reverse = (direction[0] * -1, direction[1] * -1)
        fallback.add(reverse)
        all_possible.discard(reverse)

        medio = all_possible

    elif len(moves) in (2, 3):
        for m in moves:
            ideal.add(m)
            all_possible.discard(m)

        medio.add((0, 0))
        all_possible.discard((0, 0))

        fallback = all_possible

    else:
        logging.info("How did this happen?")

    cur_best = 100, -10, source
    for d in ideal:
        cur_best = calc_move(d, cur_best)

    if cur_best[0] > 25:
        logging.info('medio')
        for d in medio:
            cur_best = calc_move(d, cur_best)

    if cur_best[0] > 25:
        logging.info('fallback')
        for d in fallback:
            cur_best = calc_move(d, cur_best)

    if cur_best[0] >= 100:
        return 100, -10, [(0, 0)]

    # now calc out own move
    num_moves, new_amount, direcs = cur_best
    if stayed:
        direcs = [(0, 0)] + direcs

    num_moves += 1 + stay_moves

    if turn == 0:
        logging.info(f'{ship.id}, {num_moves}, {new_amount}, {direcs}')
    return num_moves, new_amount, direcs