Beispiel #1
0
def safe_scan(this_ship, size):
    """
    Scans the area to be covered defined by size with respect to the current ship and does not take
    into account the positions that are currently occupied and positions that are already assigned
    to previous ships as a dictionary with "(x, y)" cordinates and "halite amount" as key, value pairs.

    :param this_ship: current ship.
    :param size: covers 2 * size from current ship's position - size to current ship's position + size in both
    (x, y) directions.

    returns: tuple of co-ordinate of maximum halite available and halite dict.
    """

    halite_dict = {(x, y): game_map[Position(x, y)].halite_amount
                   for y in range(this_ship.position.y -
                                  size, this_ship.position.y + size)
                   for x in range(this_ship.position.x -
                                  size, this_ship.position.x + size)
                   if not game_map[Position(x, y)].is_occupied and (
                       x, y) not in owned_positions and (x, y) not in IGNORE}

    TARGET = max(halite_dict, key=halite_dict.get)
    MEDIAN = median(halite_dict.values())

    ignore = rm_surrounding(Position(*TARGET), this_ship)

    return TARGET, ignore, MEDIAN
Beispiel #2
0
def find_best_cell(ship, marked_map, game_map):
    """
    Finds best cell for a ship to mine, regarding the (energy/distance) ratio
    :param ship: the ship for which the cell is to be found
    :param marked_map: map filled with RESERVED or FREE
    :game_map: the actual game map
    :return: a Position of the best cell
    """

    cell_rank = []  # lista cu rapoarte energie/distanta

    for i in range(constants.WIDTH):  # generarea de distante
        for j in range(constants.HEIGHT):
            if Position(i, j) != ship.position:
                distan = game_map[Position(
                    i, j)].halite_amount / game_map.calculate_distance(
                        ship.position, Position(i, j))
                cell_rank.insert(0, (Position(i, j), distan))

    cell_rank.sort(reverse=True,
                   key=(lambda a: a[1]))  # sortare descrescatoare

    for i in cell_rank:
        if marked_map[i[0].x][i[0].y] == FREE:
            return i[
                0]  # returneaza prima celula care nu este deja rezervata pentru alt ship
Beispiel #3
0
def find_destination(game_map):
    halite_map = []

    for y in range(game_map.height):
        for x in range(game_map.width):
            pos = Position(x, y)
            halite_map.append(game_map[pos].halite_amount)

    halite_map = np.array(halite_map)
    num = np.array(game_map.height * game_map.width * 0.1).astype(int)
    indices = np.argpartition(halite_map, -num)[-num:]

    indices = indices[np.random.randint(0, len(indices), len(indices // 2))]

    positions = []
    for idx in indices:
        positions.append(Position(idx % game_map.width,
                                  idx // game_map.height))

    dist = 999
    best_pos = positions[0]
    for pos in positions:
        d = game_map.calculate_distance(pos, ship.position)
        if d < dist:
            dist = d
            best_pos = pos

    return best_pos
Beispiel #4
0
def get_section_values(ship, game_map, turns):
    section_values = []
    for i in range(0, 8):
        section_values.append([0, 0, 0, 0, 0, 0, 0, 0])

    for x in range(-4, 4):
        for y in range(-4, 4):
            start_x = x * game_map.width / 8 + ship.position.x
            start_y = y * game_map.height / 8 + ship.position.y
            end_x = (x + 1) * game_map.width / 8 + ship.position.x
            end_y = (y + 1) * game_map.height / 8 + ship.position.y
            for section_x in range(int(start_x), int(end_x)):
                for section_y in range(int(start_y), int(end_y)):
                    if x > 0 and y > 0 and ship.id % 4 == 0:
                        section_values[x][y] += 10
                    elif x < 0 and y > 0 and ship.id % 4 == 1:
                        section_values[x][y] += 10
                    elif x < 0 and y < 0 and ship.id % 4 == 2:
                        section_values[x][y] += 10
                    elif x > 0 and y < 0 and ship.id % 4 == 3:
                        section_values[x][y] += 10
                    section_values[x][y] += 1.0 * (game_map[Position(
                        section_x, section_y)].halite_amount) / (
                            game_map.calculate_distance(
                                ship.position, Position(section_x, section_y))
                            + 1)**(1.005**(500 - turns))
    return section_values
Beispiel #5
0
def set_direction(map):
    pos = Position(random.randint(0, game_map.width - 1),
                   random.randint(0, game_map.height - 1))
    while (map[pos].halite_amount < 600):
        pos = Position(random.randint(0, game_map.width - 1),
                       random.randint(0, game_map.height - 1))
    return pos
Beispiel #6
0
def pathfinder(ship, end_position, collision_map):
    """
    Lee Algorithm
    :param ship: the ship to move
    :param end_position: the position to find the path to
    :collision_map: map filled with FREE or OCCUPIED with future movements
    :return: a list with Directions to be followed
    """

    dx = [-1, 0, 1, 0]  # vectori de directie
    dy = [0, 1, 0, -1]

    if all(collision_map[ship.position.directional_offset(curr).x][ship.position.directional_offset(curr).y] == OCCUPIED \
        for curr in [Direction.West, Direction.East, Direction.North, Direction.South]):  # daca toate directiile invecinate sunt ocupate
        return [Direction.Still]

    if end_position == ship.position:  # daca este deja pe pozitia indicata
        return [Direction.Still]

    q = Queue()

    path_matrix = np.full_like(collision_map, 0, dtype=int)  # matrice Lee
    parents_matrix = np.full_like(
        collision_map, Position(0, 0),
        dtype=Position)  # matrice reconstrcutie solutie
    q.put_nowait(ship.position)

    while not q.empty():  # Lee
        current = q.get_nowait()
        for direct in range(4):
            next_dir = Position(
                current.x + dx[direct], current.y + dy[direct],
                normalize=True)  # normalize = sa faca wrap pe margini

            if next_dir == end_position and path_matrix[next_dir.x][
                    next_dir.y] == FREE:  # sfarsit
                path_matrix[next_dir.x][next_dir.y] = path_matrix[current.x][
                    current.y] + 1  # marcheaza pozitia finala
                parents_matrix[next_dir.x][
                    next_dir.
                    y] = current  # marcheaza parintele pozitiei finale
                return traceback(end_position, path_matrix, parents_matrix,
                                 ship.position, ship)  # reconstrcutie solutie

            if collision_map[next_dir.x][next_dir.y] == FREE and path_matrix[next_dir.x][next_dir.y] == 0\
                and next_dir != ship.position:                                                    # daca nu are obstacol

                path_matrix[next_dir.x][next_dir.y] = path_matrix[current.x][
                    current.y] + 1  # incrementeaza distanta
                parents_matrix[next_dir.x][
                    next_dir.y] = current  # parintele pt traceback
                q.put_nowait(next_dir)  # adauga in coada
Beispiel #7
0
    def get_best_dir(self, ship):
        directions = {
            Direction.North: 0,
            Direction.South: 0,
            Direction.East: 0,
            Direction.West: 0
        }

        for row in range(-10, 10):
            for col in range(-10, 10):
                if col == 0 and row == 0: continue

                pos = Position(ship.position.x + col, ship.position.y + row)
                dist = self.map.calculate_distance(ship.position, pos)
                pull = self.map[pos].halite_amount / dist**2
                if self.map[pos].inspired:
                    pull *= (constants.INSPIRED_BONUS_MULTIPLIER + 1)

                for move in self.map.get_unsafe_moves(ship.position, pos):
                    directions[move] += pull

        best_safe = None
        while len(directions):
            best_direction = max(directions.items(),
                                 key=operator.itemgetter(1))[0]
            directions.pop(best_direction)
            cell = self.map[ship.position.directional_offset(best_direction)]
            if cell.safe:
                best_safe = cell
                break

        if best_safe is None:
            raise ValueError('No safe adjacent positions!')

        return best_safe
Beispiel #8
0
    def process_enemies(self):
        inspired = {}
        for player in self.game.players:
            if player is not self.game.my_id:
                for ship in self.game.players[player].get_ships():
                    # mark current enemy positions as unsafe
                    self.map[ship].mark_unsafe()

                    #  find inspired positions
                    for row in range(-constants.INSPIRATION_RADIUS,
                                     constants.INSPIRATION_RADIUS):
                        for col in range(-constants.INSPIRATION_RADIUS,
                                         constants.INSPIRATION_RADIUS):
                            x = ship.position.x + col
                            y = ship.position.y + row
                            if (x, y) in inspired:
                                inspired[(x, y)] += 1
                            else:
                                inspired[(x, y)] = 1

        #  marks these cells as being 'inspiring' to ships
        for x_y_tuple, ship_count in inspired.items():
            if ship_count >= 2:
                position = Position(x_y_tuple[0], x_y_tuple[1])
                self.map[position].mark_inspired()
Beispiel #9
0
    def get_best_dir(self, ship):
        directions = {
            Direction.North: 0,
            Direction.South: 0,
            Direction.East: 0,
            Direction.West: 0
        }

        for row in range(-10, 10):
            for col in range(-10, 10):
                pos = Position(ship.position.x + col, ship.position.y + row)
                dist = self.map.calculate_distance(ship.position, pos)
                for move in self.map.get_unsafe_moves(ship.position, pos):
                    directions[move] += self.map[pos].halite_amount / dist**2

        best_safe = None
        while len(directions):
            best_direction = max(directions.items(),
                                 key=operator.itemgetter(1))[0]
            directions.pop(best_direction)
            cell = self.map[ship.position.directional_offset(best_direction)]
            if cell.safe:
                best_safe = cell
                break

        return best_safe
Beispiel #10
0
    def calculate_halite_remaining(self):
        total = 0
        for row in range(self.map.height):
            for col in range(self.map.width):
                position = Position(row, col)
                total += self.map[position].halite_amount

        return total
Beispiel #11
0
def map_scan():
    """
    Scans the whole map for their halite amounts(resources) and returns the median of those values.
    """
    halite_dict = {(x, y): game_map[Position(x, y)].halite_amount
                   for y in range(0, game_map.height)
                   for x in range(0, game_map.width)}

    return median(halite_dict.values())
Beispiel #12
0
def surrounding_halite(game, ship, size):
    cur_position = ship.position
    sur_positions = [
        Position(cur_position.x + x, cur_position.y + y)
        for x in range(-size, size + 1) for y in range(-size, size + 1)
    ]
    sur_halites = [game.game_map[pos].halite_amount for pos in sur_positions]
    surrounding = [(sur_positions[i], sur_halites[i])
                   for i in range(len(sur_positions))]
    return surrounding
Beispiel #13
0
 def add_target(self, ship: Ship, target: Optional[Union[Position, Tuple[int, int], List[Position]]]):
     self.targets[ship] = target
     if FLOG and target:
         p = Position(*(target[-1] if isinstance(target, list) else target))
         self.f_log.append({
             "t": self.game.turn_number,
             "x": p.x,
             "y": p.y,
             "color": "#FF0000"
         })
Beispiel #14
0
def set_direction(map):
    positions = []
    halite = []

    for i in range(10):
        pos = Position(random.randint(0, game_map.width - 1),
                       random.randint(0, game_map.height - 1))
        positions.append(pos)
        halite.append(map[pos].halite_amount)

    return positions[np.argmax(halite)]
Beispiel #15
0
def rm_surrounding(pos, ship):
    """
    removes off positions surrounding the target and current ship's current position.

    :param pos: target position that should not be taken into consideration for the next ship.
    :param ship: ship position that should not be taken into consideration for the next ship.

    returns: returns list of target position, positions surrounding the target and ship's position
    """
    temp = [unpack(pos)] + [unpack(game_map.normalize(pos + Position(*direction))) for direction in Direction.get_all_cardinals()] + \
        [unpack(ship.position)]
    return temp
Beispiel #16
0
def get_map_info(game_map):
    width = game_map.width
    height = game_map.height
    halite_info = [[0 for j in range(height)] for i in range(width)]
    for i in range(width):
        for j in range(height):
            halite_info[i][j] = game_map[Position(i, j)].halite_amount

    total_halite = sum(sum(halite_info, []))
    # max_halite = max(sum(halite_info,[]))
    # min_halite = min(sum(halite_info,[]))
    avg_halite = total_halite / (width * height)

    return halite_info, total_halite, avg_halite
Beispiel #17
0
def better_around(map, pos, dir):
    x = pos.x
    y = pos.y

    best_pos = dir
    best_val = 400
    for x_i in range(-2, 2):
        for y_i in range(-2, 2):
            cur_pos = Position(x + x_i, y + y_i)
            cur_amount = map[cur_pos].halite_amount
            if (cur_amount > best_val):
                best_val = cur_amount
                best_pos = cur_pos

    return (best_val > 400), best_pos
Beispiel #18
0
 def drop_custom_map(self, view):
     debug_map = self.bot.debug_maps.get(view, None)
     if debug_map is None:
         self.draw_halite()
         return
     max_value = debug_map.max()
     min_value = debug_map.min()
     it = np.nditer(debug_map, ['multi_index'])
     while not it.finished:
         halite = it[0]
         position = Position(*reversed(it.multi_index))
         k = (max_value - min_value) or .1
         pygame.draw.rect(
             self.screen,
             mul_tuple((255, 255, 255), (halite - min_value) / k,
                       integer=True), pos2rect(position))
         it.iternext()
Beispiel #19
0
 def draw_selected(self):
     if isinstance(self.selected, Ship):
         debug_map = self.bot.debug_maps.get(self.selected.id, None)
         if debug_map is None:
             self.draw_halite()
             return
         max_value = debug_map.max()
         it = np.nditer(debug_map, ['multi_index'])
         while not it.finished:
             halite = it[0]
             position = Position(*reversed(it.multi_index))
             pygame.draw.rect(
                 self.screen,
                 mul_tuple((255, 255, 255),
                           halite / max_value,
                           integer=True), pos2rect(position))
             it.iternext()
Beispiel #20
0
def good_for_depo(game_map, me, ship):
    if not far_enough(game_map, me, ship):
        return False

    if me.halite_amount < 4100:
        return False

    x = ship.position.x
    y = ship.position.y
    halites = []
    for x_i in range(-3, 3):
        for y_i in range(-3, 3):
            pos = Position(x + x_i, y + y_i)
            halites.append(game_map[pos].halite_amount)

    if np.mean(halites) > 250:
        return True
    return False
Beispiel #21
0
def max_dest(section_values, sections_exploring, width, height,
             shipyard_position):
    max = -1
    max_x = 0
    max_y = 0
    for x in range(0, 8):
        for y in range(0, 8):
            if sections_exploring[x][y] == -1 and section_values[x][y] > max:
                max_x = x
                max_y = y
                max = section_values[x][y]
    ret_position = Position(max_x * width / 8 + random.randint(-4, 4),
                            max_y * width / 8 + random.randint(-4, 4))
    if ret_position.x == shipyard_position.x:
        ret_position.x += random.randint(1, 5)
    if ret_position.y == shipyard_position.y:
        ret_position.y += random.randint(1, 5)
    return ret_position, max_x, max_y
Beispiel #22
0
def free_ships_collided(ships, return_status, marked_map):
    """
    Frees return_status for ships that got destroyed and frees map cells that
    were reserved for those destroyed ships
    :param ships: the list of ships
    :return_status: the dictionary formed of tuples ('Free'/'Collecting'/'Ending', Position())
    :marked_map: map filled with cluster.FREE or cluster.RESERVED
    :return: the new return_status dictionary
    """
    ship_exists = [False for _ in range(500)]
    for ship in ships:  # marcheaza ship-urile care exista (dupa id unic global)
        ship_exists[ship.id] = True

    for i in range(500):
        if not ship_exists[i]:  #daca nu exista
            if return_status[str(i)][0] != "Free":  # o eliberam
                marked_map[return_status[str(i)][1].x][return_status[str(
                    i)][1].y] = 0  # eliberam si harta
            return_status[str(i)] = ("Free", Position(0, 0))

    return return_status
Beispiel #23
0
    def dropoff_builder(self) -> Tuple[Optional[Position], Optional[Ship]]:
        GAUSS_SIGMA = 2.
        MIN_HALITE_PER_REGION = 16000

        gmap = self.game.map
        bases = {
            self.game.me.shipyard.position,
            *(base.position for base in self.game.me.get_dropoffs())
        }
        halite_ex = gmap.halite_extended.copy()
        h, w, d = gmap.height, gmap.width, 2

        # Fill map border with zeros
        halite_ex[:d, 0:2 * w] = 0
        halite_ex[-d:, 0:2 * w] = 0
        halite_ex[0:2 * h, :d] = 0
        halite_ex[0:2 * h, -d:] = 0
        halite_ex_gb = gaussian_filter(halite_ex,
                                       sigma=GAUSS_SIGMA,
                                       truncate=2.0,
                                       mode='wrap')

        # Find contours of high halite deposits
        contours = msr.find_contours(halite_ex_gb,
                                     halite_ex_gb.max() * self.contour_k,
                                     fully_connected="high")
        masks = [
            poly2mask(c[:, 0], c[:, 1], halite_ex.shape) for c in contours
        ]

        # Remove small halite chunks
        good_contours = []
        for c, m in zip(contours, masks):
            if np.sum(np.multiply(gmap.halite_extended,
                                  m)) > MIN_HALITE_PER_REGION:
                good_contours.append(c)

        # Remove offset of contour points
        contours = [contour - h // 2 for contour in good_contours]

        # Set up possible dropoff points
        points = {
            tuple(float(round(x)) for x in point)
            for contour in contours for point in contour
        }
        points = [
            list(point) for point in points
            if all(0 <= x < h
                   for x in point) and Position(*map(int, point)) not in bases
        ]
        points = np.array(points, dtype=np.int)
        if points.shape[0] == 0:
            return None, None

        # Create potential field
        potential_field = np.zeros(gmap.halite.shape, dtype=np.float)
        for player in self.game.players.values():
            me = player is self.game.me
            for ship in player.get_ships():
                if me:
                    potential_field[ship.position.y,
                                    ship.position.x] += self.dropoff_my_ship
                else:
                    potential_field[ship.position.y,
                                    ship.position.x] += self.dropoff_enemy_ship
            for base in player.get_dropoffs():
                if me:
                    potential_field[base.position.y,
                                    base.position.x] += self.dropoff_my_base
                else:
                    potential_field[base.position.y,
                                    base.position.x] += self.dropoff_enemy_base
            pos = player.shipyard.position
            potential_field[
                pos.y, pos.
                x] += self.dropoff_my_base if me else self.dropoff_enemy_base
        potential_field = gaussian_filter(potential_field,
                                          sigma=self.potential_gauss_sigma,
                                          truncate=3.0,
                                          mode='wrap')

        if self.callbacks:
            self.debug_maps['dropoff'] = potential_field

        # Overlay points and potential_field
        potential_field_filtered = np.full(potential_field.shape,
                                           0,
                                           dtype=np.float)
        x, y = points[:, 0], points[:, 1]
        potential_field_filtered[x, y] = potential_field[x, y]

        self.debug_maps['dropoff_2'] = potential_field_filtered
        y, x = np.unravel_index(potential_field_filtered.argmax(),
                                potential_field_filtered.shape)
        value = potential_field_filtered[y, x]
        logging.debug(f"DROPOFF -> {value:.6f}")
        if value < self.dropoff_threshold:
            return None, None

        ships = self.game.me.get_ships()
        target = Position(x, y)
        distance = lambda ship: gmap.distance(ship.position, target)
        # ship_filter= lambda ship: ship.halite_amount / constants.MAX_HALITE < self.ship_fill_k * .75
        ship = min(ships, key=distance)
        return target, ship
Beispiel #24
0
 else: # exploring ships
     if (game_map[ship.position].halite_amount > constants.MAX_HALITE / greedy and not ship.is_full) \
     or game_map[ship.position].halite_amount / 10 > ship.halite_amount:
         move = Direction.Still
     else:
         best_x = ship.position.x
         best_y = ship.position.y
         maxHLT = 0;
         
         search_len = 6
         
         for i in range(-search_len, search_len + 1):
             for j in range(-search_len, search_len + 1):
                 curr_x = ship.position.x + i
                 curr_y = ship.position.y + j
                 if game_map[Position(curr_x, curr_y)].halite_amount > maxHLT:
                     maxHLT = game_map[Position(curr_x, curr_y)].halite_amount
                     best_x = curr_x
                     best_y = curr_y
                     
         move = game_map.naive_navigate(ship, Position(best_x, best_y))
         # if ship.position == me.shipyard.position:
         #     move = random.choice(Direction.get_all_cardinals())
         for current_direction in Direction.get_all_cardinals():
             pos = ship.position.directional_offset(current_direction)
             if game_map[pos].halite_amount > constants.MAX_HALITE / greedy:
                 move = current_direction
 
 if stuck_cnt[ship.id] > 5:
     move = random.choice(Direction.get_all_cardinals())
 
Beispiel #25
0
    def loop(self):
        me = self.game.me
        my_ships = me.get_ships()
        gmap = self.game.map
        home = self.game.me.shipyard.position
        moves: Dict[Ship, Iterable[Tuple[int, int]]] = {}
        bases = {home, *(base.position for base in me.get_dropoffs())}

        # Check whether new dropoff can be created or not
        if self.building_dropoff is None:
            if 10 < self.game.turn_number < constants.MAX_TURNS * self.dropoff_spawn_stop_turn:
                dropoff_position, dropoff_ship = self.dropoff_builder()
            else:
                dropoff_position, dropoff_ship = None, None
        else:
            dropoff_position, dropoff_ship = self.building_dropoff
            if not dropoff_ship.exists:
                dropoff_position, dropoff_ship = None, None
                self.building_dropoff = None

        if dropoff_ship is not None and dropoff_position is not None:
            if me.halite_amount > constants.DROPOFF_COST:
                if dropoff_ship.position == dropoff_position:
                    # If ship in place wait until we have enough halite to build dropoff
                    if me.halite_amount + dropoff_ship.halite_amount > constants.DROPOFF_COST:
                        yield dropoff_ship.make_dropoff()
                        me.halite_amount -= constants.DROPOFF_COST - dropoff_ship.halite_amount
                        logging.info(
                            f"Building dropoff {dropoff_position} from Ship#{dropoff_ship.id}"
                        )
                        self.building_dropoff = None
                    else:
                        yield dropoff_ship.stay_still()
                else:
                    # Move to new dropoff position
                    self.ship_manager.add_target(dropoff_ship,
                                                 dropoff_position)
                    self.building_dropoff = dropoff_position, dropoff_ship
                    logging.info(
                        f"Ship#{dropoff_ship.id} moving to dropoff position {dropoff_position}"
                    )
                    path = gmap.a_star_path_search(dropoff_ship.position,
                                                   dropoff_position)
                    moves[dropoff_ship] = (
                        gmap.normalize_direction(path[0] -
                                                 dropoff_ship.position), )
            else:
                yield dropoff_ship.stay_still()

        # General mask
        # Contains:
        # * enemy ship penalty
        # * penalty for cells around enemy ships (4 directions)
        # * friendly dynamic penalty based on ship cargo / cell halite ratio
        self.mask.fill(1.)
        for player in self.game.players.values():
            for ship in player.get_ships():
                if player is not me:
                    self.mask[ship.position.y,
                              ship.position.x] *= self.enemy_ship_penalty
                    for dir in Direction.All:
                        pos = gmap.normalize(ship.position + dir)
                        self.mask[pos.y,
                                  pos.x] *= self.enemy_ship_nearby_penalty
                else:
                    self.mask[
                        ship.position.y,
                        ship.position.x] *= ship_collecting_halite_coefficient(
                            ship, gmap)

        if not self.fast_mode:
            self.blurred_halite = gaussian_filter(gmap.halite,
                                                  sigma=2,
                                                  truncate=2.0,
                                                  mode='wrap')
            gbh_min, gbh_max = self.blurred_halite.min(
            ), self.blurred_halite.max()
            self.blurred_halite -= gbh_min
            self.blurred_halite /= gbh_max - gbh_min
            if self.callbacks:
                self.debug_maps["gbh_norm"] = self.blurred_halite
            self.filtered_halite *= self.blurred_halite / 2 + .5

        max_halite: float = gmap.halite.max()
        self.filtered_halite[:, :] = gmap.halite[:, :]
        self.filtered_halite[self.filtered_halite < max_halite *
                             self.halite_threshold] = 0
        self.filtered_halite *= self.mask

        # Generate moves for ships from mask and halite field
        for ship in reversed(self.ship_manager.ships):
            if ship == dropoff_ship:
                continue

            # Ship unloading
            to_home = ship in self.ships_to_home
            if to_home and ship.position in bases:
                logging.info(f"Ship#{ship.id} unload")
                self.ships_to_home.remove(ship)
                to_home = False

            if to_home or ship.halite_amount >= constants.MAX_HALITE * self.ship_fill_k:
                logging.info(f"Ship#{ship.id} moving home")
                self.ships_to_home.add(ship)
                ship_target = min(
                    bases, key=lambda base: gmap.distance(ship.position, base))
                path = gmap.a_star_path_search(ship.position, ship_target)
                self.ship_manager.add_target(ship, path)
                moves[ship] = (gmap.normalize_direction(path[0] -
                                                        ship.position), )

            # Ship has too low halite to move
            elif gmap[
                    ship].halite_amount / constants.MOVE_COST_RATIO > ship.halite_amount:
                yield ship.stay_still()
                continue

            else:
                self.per_ship_mask.fill(1.0)
                for another_ship, target in self.ship_manager.targets.items():
                    if isinstance(target, list):
                        target = target[0]
                    if another_ship is ship or target is None or target == home:
                        continue
                    self.per_ship_mask[target[1],
                                       target[0]] *= self.same_target_penalty
                self.weighted_halite[:, :] = self.filtered_halite[:, :]

                # Apply masks
                distances = np.roll(self.distances, ship.position.y, axis=0)
                distances = np.roll(distances, ship.position.x, axis=1)
                self.weighted_halite /= distances
                self.weighted_halite *= self.per_ship_mask
                self.weighted_halite[
                    ship.position.y,
                    ship.position.x] /= ship_collecting_halite_coefficient(
                        ship, gmap)

                if self.callbacks:
                    self.debug_maps[ship.id] = self.weighted_halite.copy()

                # Found max point
                y, x = np.unravel_index(self.weighted_halite.argmax(),
                                        self.weighted_halite.shape)
                max_halite = self.weighted_halite[y, x]
                if max_halite > 0.1:
                    target = Position(x, y)
                    if target is dropoff_position:
                        continue
                    if target == ship.position:
                        logging.info(f"Ship#{ship.id} collecting halite")
                        self.ship_manager.add_target(ship, None)
                        yield ship.stay_still()
                    else:
                        logging.info(
                            f"Ship#{ship.id} {ship.position} moving towards {target}"
                        )
                        self.ship_manager.add_target(ship, target)
                        moves[ship] = list(
                            self.game.map.get_unsafe_moves(
                                ship.position, target))
                else:
                    logging.info(
                        f"Ship#{ship.id} does not found good halite deposit")
                    self.ship_manager.add_target(ship, None)
                    yield ship.stay_still()

        # Resolve moves into commands in 2 iterations
        moves: List[Tuple[Ship, Iterable[Tuple[int,
                                               int]]]] = list(moves.items())
        for i in range(2):
            commands, moves = self.resolve_moves(moves)
            yield from commands

        # Remaining ship has not any safe moves
        for ship, d in moves:
            logging.debug(f"Unsafe move: {ship} -> {d}")
            yield ship.stay_still()

        # Max ships: base at 32 map size, 2*base at 64 map size
        if ((dropoff_position is None or
             me.halite_amount >= constants.SHIP_COST + constants.DROPOFF_COST)
                and self.game.turn_number <=
                constants.MAX_TURNS * self.ship_turns_stop
                and me.halite_amount >= constants.SHIP_COST
                and not gmap[me.shipyard].is_occupied
                and self.max_ships_reached <= 2):
            if len(my_ships) < self.ship_limit:
                yield me.shipyard.spawn()
            else:
                self.max_ships_reached += 1
Beispiel #26
0
 def test_collect_halite(self):
     print(nav.collect_halite(game_map, Position(0, 0)))
     self.assertEqual('foo'.upper(), 'FOO')
Beispiel #27
0
    def loop(self):
        me = self.game.me
        my_ships = me.get_ships()
        gmap = self.game.map
        total_halite = gmap.total_halite
        home = self.game.me.shipyard.position
        moves: Dict[Ship, Iterable[Tuple[int, int]]] = {}
        bases = {home, *(base.position for base in me.get_dropoffs())}

        # Check whether new dropoff can be created or not
        if self.building_dropoff is None:
            if 10 < self.game.turn_number < constants.MAX_TURNS * self.dropoff_spawn_stop_turn:
                dropoff_position, dropoff_ship = self.dropoff_builder()
            else:
                dropoff_position, dropoff_ship = None, None
        else:
            dropoff_position, dropoff_ship = self.building_dropoff
            if not dropoff_ship.exists:
                dropoff_position, dropoff_ship = None, None
                self.building_dropoff = None

        if dropoff_ship is not None and dropoff_position is not None:
            if dropoff_ship.position == dropoff_position:
                # If ship in place wait until we have enough halite to build dropoff
                if me.halite_amount + dropoff_ship.halite_amount > constants.DROPOFF_COST:
                    yield dropoff_ship.make_dropoff()
                    me.halite_amount -= constants.DROPOFF_COST - dropoff_ship.halite_amount
                    logging.info(
                        f"Building dropoff {dropoff_position} from Ship#{dropoff_ship.id}"
                    )
                    self.building_dropoff = None
                else:
                    yield dropoff_ship.stay_still()
            else:
                # Move to new dropoff position
                self.ship_manager.add_target(dropoff_ship, dropoff_position)
                self.building_dropoff = dropoff_position, dropoff_ship
                logging.info(
                    f"Ship#{dropoff_ship.id} moving to dropoff position {dropoff_position}"
                )
                path = gmap.a_star_path_search(dropoff_ship.position,
                                               dropoff_position)
                moves[dropoff_ship] = (
                    gmap.normalize_direction(path[0] -
                                             dropoff_ship.position), )

        # Ships mask
        # Contains:
        # * enemy ship penalty
        # * penalty for cells around enemy ships (4 directions)
        # * inspiration bonus based on halite estimation of player
        self.ships_mask.fill(0.)
        players_halite: Dict[Player, int] = {
            p: p.halite_estimate
            for p in self.game.players.values()
        }
        players_sorted: List[Tuple[Player,
                                   int]] = sorted(players_halite.items(),
                                                  key=operator.itemgetter(1),
                                                  reverse=True)
        my_halite = players_halite[me]
        top_player_warning = players_sorted[0][
            0] is not me and players_sorted[0][1] - my_halite > 5000
        enable_inspiration = len(players_sorted) > 2
        for i, (player, _) in enumerate(players_sorted):
            if player is me:
                continue
            for ship in player.get_ships():
                self.ships_mask += roll2d(self.inspiration_mask,
                                          *ship.position)

            # k := 1 | 2
            if enable_inspiration:
                k = min(i + 1 if i else 1, 2) if top_player_warning else 2
            else:
                k = 1
            np.clip(self.ships_mask, -np.inf, k, out=self.ships_mask)
        # Replace mask pseudo value with real coefficients
        self.ships_mask[self.ships_mask < -300.0] = self.enemy_ship_penalty
        self.ships_mask[self.ships_mask < 0.0] = self.enemy_ship_penalty * 2
        self.ships_mask[self.ships_mask == 0.0] = 1.0
        self.ships_mask[self.ships_mask == 2.0] = self.inspiration_bonus
        np.clip(self.ships_mask,
                self.enemy_ship_penalty,
                self.inspiration_bonus,
                out=self.ships_mask)
        if self.callbacks:
            self.debug_maps["ships_mask"] = self.ships_mask

        # If we have time - apply blurred mask
        if not self.fast_mode:
            gaussian_filter(gmap.halite,
                            sigma=2,
                            truncate=2.0,
                            mode='wrap',
                            output=self.blurred_halite)
            gbh_min, gbh_max = self.blurred_halite.min(
            ), self.blurred_halite.max()
            self.blurred_halite -= gbh_min
            if gbh_max - gbh_min != 0.0:
                self.blurred_halite /= gbh_max - gbh_min
            if self.callbacks:
                self.debug_maps["gbh_norm"] = self.blurred_halite
            self.filtered_halite *= self.blurred_halite / 2 + .5

        # Filter halite:
        # * reduce halite spikes after ships collide
        # * remove everything that is less than self.halite_threshold
        self.filtered_halite[:, :] = gmap.halite[:, :]
        self.filtered_halite[self.filtered_halite < self.halite_threshold] = 0
        if len(players_sorted) > 2:
            ix = self.filtered_halite > (self.filtered_halite.mean()**2)
            self.filtered_halite[ix] = (self.filtered_halite[ix]**0.5) * 2

        if len(self.game.players) == 2:
            enemy_2p = [p for p in self.game.players.values()
                        if p is not me][0]
            ram_enabled = len(me.get_ships()) > len(enemy_2p.get_ships()) + 10
        else:
            ram_enabled = False
        ram_enabled = ram_enabled or total_halite / gmap.initial_halite <= 0.13

        # Generate moves for ships from masks and halite field
        for ship in reversed(self.ship_manager.ships):
            if ship == dropoff_ship:
                continue

            # Ship unloading
            to_home = ship in self.ships_to_home
            if to_home and ship.position in bases:
                logging.info(f"Ship#{ship.id} unload")
                self.ships_to_home.remove(ship)
                to_home = False

            if to_home or ship.halite_amount >= constants.MAX_HALITE * self.ship_fill_k:
                logging.info(f"Ship#{ship.id} moving home")
                self.ships_to_home.add(ship)
                ship_target = min(
                    bases, key=lambda base: gmap.distance(ship.position, base))
                path = gmap.a_star_path_search(ship.position,
                                               ship_target,
                                               my_id=me.id)
                self.ship_manager.add_target(ship, path)
                moves[ship] = (gmap.normalize_direction(path[0] -
                                                        ship.position), )

            # Ship has too low halite to move
            elif gmap[
                    ship].halite_amount / constants.MOVE_COST_RATIO > ship.halite_amount:
                yield ship.stay_still()
                continue

            else:
                if ram_enabled:
                    # Ram enemy ship with a lot of halite
                    for direction in Direction.All:
                        other_ship = gmap[ship.position + direction].ship
                        if not other_ship or other_ship.owner == me.id:
                            continue
                        if other_ship.halite_amount / (ship.halite_amount +
                                                       1) >= 3:
                            target_found = True
                            break
                    else:
                        target_found = False
                    if target_found:
                        # noinspection PyUnboundLocalVariable
                        logging.info(
                            f"Ship#{ship.id} ramming enemy ship #{other_ship.id}"
                            f" ({ship.halite_amount}) vs ({other_ship.halite_amount})"
                        )
                        # noinspection PyUnboundLocalVariable
                        yield gmap.update_ship_position(ship, direction)
                        continue

                self.per_ship_mask.fill(1.0)
                for another_ship, target in self.ship_manager.targets.items():
                    if isinstance(target, list):
                        target = target[0]
                    if another_ship is ship or target is None or target == home:
                        continue
                    self.per_ship_mask[target[1],
                                       target[0]] *= self.same_target_penalty
                self.weighted_halite[:, :] = self.filtered_halite[:, :]

                # Ship mask is filtered by distance
                distances = roll2d(self.distances, *ship.position)
                ships_mask = np.copy(self.ships_mask)
                ix = distances > self.inspiration_track_radius
                ships_mask[ix] = np.clip(ships_mask[ix], 0, 1)

                # Apply masks
                self.weighted_halite *= ships_mask
                self.weighted_halite *= self.per_ship_mask
                self.weighted_halite /= (distances +
                                         1)**self.distance_penalty_k
                # self.weighted_halite[ship.position.y, ship.position.x] /= ship_collecting_halite_coefficient(ship, gmap)
                self.weighted_halite[ship.position.y,
                                     ship.position.x] *= self.stay_still_bonus

                if self.callbacks:
                    self.debug_maps[ship.id] = self.weighted_halite.copy()

                # Found max point
                y, x = np.unravel_index(self.weighted_halite.argmax(),
                                        self.weighted_halite.shape)
                max_halite = self.weighted_halite[y, x]
                if max_halite > 0:
                    target = Position(x, y)
                    if target is dropoff_position:
                        continue
                    if target == ship.position:
                        logging.info(f"Ship#{ship.id} collecting halite")
                        self.ship_manager.add_target(ship, None)
                        yield ship.stay_still()
                    else:
                        logging.info(
                            f"Ship#{ship.id} {ship.position} moving towards {target}"
                        )
                        self.ship_manager.add_target(ship, target)
                        moves[ship] = list(
                            self.game.map.get_unsafe_moves(
                                ship.position, target))
                else:
                    logging.info(
                        f"Ship#{ship.id} does not found good halite deposit")
                    self.ship_manager.add_target(ship, None)
                    yield ship.stay_still()

        moves: List[Tuple[Ship, Iterable[Tuple[int,
                                               int]]]] = list(moves.items())
        yield from self.ship_manager.resolve_moves(moves)

        # Max ships: base at 32 map size, 2*base at 64 map size
        shipyard_cell = gmap[me.shipyard]
        if ((self.building_dropoff is None
             and me.halite_amount >= constants.SHIP_COST
             or self.building_dropoff is not None
             and all(self.building_dropoff) and
             me.halite_amount >= constants.SHIP_COST + constants.DROPOFF_COST)
                and self.max_ships_reached <= 3 and
            (shipyard_cell.ship is None or shipyard_cell.ship.owner != me.id)):
            if (total_halite / gmap.initial_halite >= .25
                    and self.game.turn_number <=
                    constants.MAX_TURNS * self.ship_turns_stop
                    or total_halite / gmap.initial_halite >= .57
                    and self.game.turn_number <= constants.MAX_TURNS *
                (1 - (1 - self.ship_turns_stop) / 1.5)):
                if len(my_ships) < self.ship_limit:
                    yield me.shipyard.spawn()
                else:
                    self.max_ships_reached += 1
Beispiel #28
0
                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)


    #game_map[ship.position].mark_unsafe(ship)




Shipyard = Position(8, 16)

""" <<<Game Loop>>> """
while True:
    # This loop handles each turn of the game. The game object changes every turn, and you refresh that state by
    #   running update_frame().
    game.update_frame()
    # You extract player metadata and the updated map metadata here for convenience.
    me = game.me
    game_map = game.game_map
    
    # A command queue holds all the commands you will run this turn. You build this list up and submit it at the
    #   end of the turn.
    command_queue = []
    placepicked = []
    placepicked.clear()
Beispiel #29
0
    def loop(self):
        me = self.game.me
        my_ships = me.get_ships()
        gmap = self.game.map
        home = self.game.me.shipyard.position

        # General mask
        # Contains:
        # * enemy ship penalty
        # * penalty for cells around enemy ships (4 directions)
        # * friendly dynamic penalty based on ship cargo / cell halite ratio
        self.mask.fill(1.)
        for player in self.game.players.values():
            for ship in player.get_ships():
                if player is not me:
                    self.mask[ship.position.y][
                        ship.position.x] *= self.enemy_ship_penalty
                    for dir in Direction.All:
                        pos = gmap.normalize(ship.position + dir)
                        self.mask[pos.y][
                            pos.x] *= self.enemy_ship_nearby_penalty
                else:
                    self.mask[ship.position.y][
                        ship.position.x] *= ship_collecting_halite_coefficient(
                            ship, gmap)

        if not self.fast_mode:
            for y, row in enumerate(gmap.cells):
                for x, cell in enumerate(row):
                    self.blurred_halite[y][x] = cell.halite_amount
            self.blurred_halite = gaussian_filter(self.blurred_halite,
                                                  sigma=2,
                                                  truncate=2.0,
                                                  mode='wrap')
            gbh_min, gbh_max = self.blurred_halite.min(
            ), self.blurred_halite.max()
            self.blurred_halite -= gbh_min
            self.blurred_halite /= gbh_max - gbh_min
            if self.callbacks:
                self.debug_maps["gbh_norm"] = self.blurred_halite

        # Generate moves for ships from mask and halite field
        moves: List[Tuple[Ship, Iterable[Tuple[int, int]]]] = []
        for ship in my_ships:
            # Ship unloading
            to_home = ship in self.ships_to_home
            if to_home and ship.position == home:
                logging.info(f"Ship#{ship.id} unload")
                self.ships_to_home.remove(ship)
                to_home = False

            if to_home or ship.halite_amount >= constants.MAX_HALITE * self.ship_fill_k:
                logging.info(f"Ship#{ship.id} moving home")
                self.ships_to_home.add(ship)
                self.ships_targets[ship] = path = gmap.a_star_path_search(
                    ship.position, home)
                moves.append(
                    (ship,
                     (gmap.normalize_direction(path[0] - ship.position), )))

            else:
                self.per_ship_mask.fill(1.0)
                for another_ship, target in self.ships_targets.items():
                    if isinstance(target, list):
                        target = target[0]
                    if another_ship is ship or target is None or target == home:
                        continue
                    self.per_ship_mask[target[1]][
                        target[0]] *= self.same_target_penalty

                # Ship has too low halite to move
                if gmap[ship].halite_amount / constants.MOVE_COST_RATIO > ship.halite_amount:
                    # self.ships_targets[ship] = None
                    yield ship.stay_still()
                    continue

                position = None
                # if gmap.width // 2 - 1 > self.lookup_radius:
                #     field = ship.position.get_surrounding_cardinals(self.lookup_radius, center=True)
                # else:
                for coord in map(operator.attrgetter('position'), gmap):
                    self.weights[coord.y][coord.x] = gmap[coord].halite_amount

                # Apply masks
                if not self.fast_mode:
                    self.weights *= self.blurred_halite / 2 + .5
                self.weights *= self.mask
                self.weights *= self.per_ship_mask
                it = np.nditer(self.weights, ['multi_index'], ['readwrite'])
                while not it.finished:
                    y, x = it.multi_index
                    distance = gmap.distance(ship.position, (x, y))
                    if distance:
                        # Distance penalty
                        # TODO: Experiment with A* algorithm
                        it[0] /= (distance + 1)**self.distance_penalty_k
                    else:
                        # Revert "same point penalty" of current ship
                        it[0] /= ship_collecting_halite_coefficient(ship, gmap)
                    it.iternext()

                if self.callbacks:
                    self.debug_maps[ship.id] = self.weights.copy()

                # Found max point
                y, x = np.unravel_index(self.weights.argmax(),
                                        self.weights.shape)
                max_halite: Tuple[Position,
                                  int] = (Position(x, y), self.weights[y][x])
                if max_halite[1] > 0.1:
                    position = max_halite[0]

                if position:
                    if position == ship.position:
                        logging.info(f"Ship#{ship.id} collecting halite")
                        self.ships_targets[ship] = None
                        yield ship.stay_still()
                    else:
                        logging.info(
                            f"Ship#{ship.id} {ship.position} moving towards {position}"
                        )
                        self.ships_targets[ship] = position
                        moves.append((ship,
                                      list(
                                          self.game.map.get_unsafe_moves(
                                              ship.position, position))))
                else:
                    logging.info(
                        f"Ship#{ship.id} does not found good halite deposit")
                    self.ships_targets[ship] = None
                    yield ship.stay_still()

        # Resolve moves into commands in 2 iterations
        for i in range(2):
            commands, moves = self.resolve_moves(moves)
            yield from commands

        # Remaining ship has not any safe moves
        for ship, d in moves:
            logging.debug(f"Unsafe move: {ship} -> {d}")
            yield ship.stay_still()

        # Max ships: base at 32 map size, 2*base at 64 map size
        if (self.game.turn_number <= constants.MAX_TURNS * self.ship_turns_stop
                and me.halite_amount >= constants.SHIP_COST
                and not gmap[me.shipyard].is_occupied
                and self.max_ships_reached <= 2):
            if len(my_ships) < self.ship_limit:
                yield me.shipyard.spawn()
            else:
                self.max_ships_reached += 1
Beispiel #30
0
        if index % 10 == 0:
            MEDIAN = map_scan()

        if game.turn_number < rush:

            if ship_status[
                    ship.id][0] == explore and ship.id not in commanded_ships:
                max_halite_cord = target_positions[ship.id]

                if game_map[ship.position].halite_amount > MEDIAN * .7:
                    move = Direction.Still
                    commands.append(ship.move(move))
                    commanded_ships[ship.id] = index

                else:
                    move = Navigator(ship, Position(*max_halite_cord), index)
                    ship_status[ship.id][1] = ship.position.directional_offset(
                        move)
                    commands.append(ship.move(move))
                    commanded_ships[ship.id] = index

            if ship_status[
                    ship.id][0] == ret and ship.id not in commanded_ships:

                if ship.position == me.shipyard.position:
                    ship_status[ship.id][0] = explore

                else:
                    gain = calculate_gain(ship)

                    if gain > threshold or ship.is_full: