예제 #1
0
파일: RVO.py 프로젝트: gplays/HaliteBot
def find_adhesion_cone_circle_centered(b, r):
    """
    Compute the coordinates of the intersection between the circle of center
    b and radius r and its tangent passing by a. A is at the origin of the space

    :param b: Position of point B
    :type b: Position
    :param r: Sum of the radius of A and B
    :type r: float
    :return: The coordinates of the intersections
    :rtype: tuple(Position)
    """
    d2 = b.x**2 + b.x**2
    r2 = r**2
    norm_c_2 = d2 - r2
    norm_c = math.sqrt(norm_c_2)

    # NB can be solved with determinant computation
    # Solving using scalar product and vectorial product and using the
    # the geometrical projection to have explicit expression of sin and cos
    p1 = Position(*solve_x_y([b.x, -b.x], [b.x, b.x], [norm_c_2, norm_c * r]))

    p2 = Position(*solve_x_y([b.x, b.x], [b.x, -b.x], [norm_c_2, norm_c * r]))

    return (p1, p2)
예제 #2
0
    def has_planet(self, x, y):
        if x <= 0 or x >= self._game.map.width or y <= 0 or y >= self._game.map.height:
            return True
        pos = Position(x, y)
        for planet in self._game.map.all_planets():
            if pos.calculate_distance_between(
                    planet) <= planet.radius + .50001:
                return True

        return False
예제 #3
0
def ship_against_ship(ship, enemy_ship, game_map):
    p = Position(enemy_ship.x, enemy_ship.y)
    c = ship.navigate(p,
                      game_map,
                      speed=int(hlt.constants.MAX_SPEED),
                      ignore_ships=False,
                      ignore_planets=False)
    if not c:
        logging.warning("Couldn't attack enemy %s with ship %s" %
                        (enemy_ship.id, ship.id))
    return c
예제 #4
0
def attack_planet(ship, planet, game_map):
    p = Position(planet.x, planet.y)
    c = ship.navigate(
        p,
        game_map,
        speed=int(hlt.constants.MAX_SPEED),
        ignore_ships=False,
        ignore_planets=False)
    if not c:
        logging.warning("Couldn't attack planet %s with ship %s" % (planet.id, ship.id))
    return c
예제 #5
0
    def regroup(self):
        """
        # Order all drone to move to center
        :return:
        """
        center = self.gravitational_center()
        position = Position(center.x, center.y)
        position.pos.radius = self.nb_members() * SQUAD_SCATTERED_THRESHOLD / 2.0
        # Assign the position as target

        self.assign_target(position, target_type=TargetType.POSITION)
예제 #6
0
def attack_planet(ship, planet, game_map):
    p = Position(planet.x, planet.y)
    c = None
    speed = int(hlt.constants.MAX_SPEED)
    while speed > 0:
        c = ship.navigate(
            p,
            game_map,
            speed=speed,
            ignore_ships=True,
            ignore_planets=True)
        if c:
            return c
        speed -= 1
    logging.warning("Couldn't attack planet %s with ship %s" % (planet.id, ship.id))
    return c
예제 #7
0
def cornershipmove():
    ship = cornershipfinder()
    shippos = np.array([[ship.x, ship.y]])
    corners = np.array([[0, 0], [game_map.width, game_map.height],
                        [0, game_map.height], [game_map.width, 0]])
    distances = scipy.spatial.distance.cdist(shippos, corners)
    index, distance = min(enumerate(distances[0]),
                          key=lambda distance: distance[1])
    desiredcornerX, desiredcornerY = corners[index]
    navigate_command = ship.navigate(ship.closest_point_to(
        Position(desiredcornerX, desiredcornerY)),
                                     game_map,
                                     speed=int(hlt.constants.MAX_SPEED),
                                     ignore_ships=False,
                                     angular_step=8)
    if navigate_command:
        command_queue.append(navigate_command)
예제 #8
0
    def test_compute_1RVOCone_constraint(self):
        m = 4
        n = 1
        all_entities = self.entities[:m]
        all_entities[1].vel = Position(0, -20)
        preprocess = constraints_pre_cone(n, m, all_entities, self.max_speed)
        all_pos, diff_pos, sum_rad, u1, u2, u3, d3, speed_sq, collision_idx, \
        prev_vel = preprocess

        cons = const_RVO_cone(diff_pos, sum_rad, u1, u2, u3, d3, speed_sq,
                              collision_idx, prev_vel)
        x = self.entities[0].x
        y = self.entities[0].y

        cons((100 - x, 40 - y))
        n_cons = len(cons([0, 0]))

        # for k in range(n_cons):
        #     print("#"*10)
        #     for j in range(20):
        #         print(" ".join(["{:3}".format(cons([i * 10 - x, j * 10 -
        #                                              y])[k]<=0)
        #                       for i in range(20)]))
        # for k in range(n_cons):
        #     print("#"*10)
        #     img = [[cons([i - x, j - y])[k] < 0
        #             for i in range(200)]
        #            for j in range(200)]
        #     img = np.array(img, dtype=np.uint8)
        #     img = img * 255
        #     img = np.dstack((img, img, img))
        #     draw_entities(img, all_entities)

        img = [[
            all([cons([i - x, j - y])[k] < 0 for k in range(n_cons)])
            for i in range(200)
        ] for j in range(200)]

        img = np.array(img, dtype=np.uint8)
        img = img * 255
        img = np.dstack((img, img, img))

        draw_entities(img, all_entities)
예제 #9
0
    def __init__(self, load_from_disk=None, debug=False, args=None):
        self._t0 = time.time()
        self._game = pw.load('game_init.p') if load_from_disk else hlt.Game(
            'DaanV123' + ('_debug' if debug else ''))
        self._debug = debug
        self._turn_idx = 0
        if self._debug:
            pw.dump(self._game, "game_init.p")
            pw.dump(args, "args.p")

        if load_from_disk:
            args = pw.load("args.p")
            print(args)

        self._num_players = len(self._game.map.all_players())
        heads_up = self._num_players == 2
        self._r_attack_docked = args.r_attack_docked
        self._r2_chase_enemy = args.r_chase_enemy**2
        self._enemy_weight = args.enemy_weight_2p if heads_up else args.enemy_weight_4p
        self._unowned_planet_weight = args.unowned_planet_weight
        self._r_enemy_no_dock = args.r_enemy_no_dock
        self._owned_planet_weight = args.owned_planet_weight
        self._enemy_planet_weight = args.enemy_planet_weight
        self._expected_enemy_theta = args.expected_enemy_theta

        self._distances_to_planets = {
            planet.id: compute_distances(self._game.map, planet.x, planet.y,
                                         planet.radius + 3)
            for planet in self._game.map.all_planets()
        }

        center = Position(self._game.map.width / 2, self._game.map.height / 2)
        self._planet_distance_from_center = {
            planet.id: planet.calculate_distance_sq_between(center)
            for planet in self._game.map.all_planets()
        }

        self._should_i_dock = True
        self._should_i_undock = False
        self._hide = False
        self.compute_stuff()
예제 #10
0
    def intersect_segment_circle(start, end, circle, *, fudge=0.5):
        """
        Test whether a line segment and circle intersect.

        :param Entity start: The start of the line segment. (Needs x, y attributes)
        :param Entity end: The end of the line segment. (Needs x, y attributes)
        :param Entity circle: The circle to test against. (Needs x, y, r attributes)
        :param float fudge: A fudge factor; additional distance to leave between the segment and circle. (Probably set this to the ship radius, 0.5.)
        :return: True if intersects, False otherwise
        :rtype: bool
        """
        # Derived with SymPy
        # Parameterize the segment as start + t * (end - start),
        # and substitute into the equation of a circle
        # Solve for t
        dx = end.x - start.x
        dy = end.y - start.y

        a = dx**2 + dy**2
        b = -2 * (start.x**2 - start.x * end.x - start.x * circle.x +
                  end.x * circle.x + start.y**2 - start.y * end.y -
                  start.y * circle.y + end.y * circle.y)
        c = (start.x - circle.x)**2 + (start.y - circle.y)**2

        if a == 0.0:
            # Start and end are the same point
            return start.calculate_distance_between(
                circle) <= circle.radius + fudge

        # Time along segment when closest to the circle (vertex of the quadratic)
        t = min(-b / (2 * a), 1.0)
        if t < 0:
            return False

        closest_x = start.x + dx * t
        closest_y = start.y + dy * t
        closest_distance = Position(
            closest_x, closest_y).calculate_distance_between(circle)

        return closest_distance <= circle.radius + fudge
예제 #11
0
def get_centroid(entities: List[Entity], width: float,
                 height: float) -> Position:
    """
    Calculate centroid of entities.
    :param entities:
    :param width:
    :param height:
    :return: Position
    """
    cx, cy = 0.0, 0.0

    if entities:
        for entity in entities:
            cx += entity.x
            cy += entity.y
        cx /= len(entities)
        cy /= len(entities)
        if width:
            cx /= width
        if height:
            cy /= height

    return Position(cx, cy)
예제 #12
0
                    rem_dock[e] -= 1
                    cmds.append(nav_cmd)
                if move:
                    move_table[s] = move
            unassigned.discard(s)
        elif type(e) == hlt.entity.Ship:

            # WITHIN POTENTIAL ATTACK RANGE
            if s.dist_to(e) <= WEAPON_RADIUS + 2*MAX_SPEED:
                # ATTACK
                if s in has_atked:
                    nav_cmd, move = helper.nav(s,s.closest_pt_to(e,6),gmap,None,move_table)
                else:
                    nav_cmd, move = helper.nav(s,s.closest_pt_to(e),gmap,None,move_table)
                if move:
                    atk_pos = Position(move.p2)
                else:
                    atk_pos = Position(s.loc, s.loc + Point.polar(MAX_SPEED,s.angle_to(e)))
                atk_ens = [t for t in gmap.en_uships() if t.dist_to(atk_pos) <= WEAPON_RADIUS + MAX_SPEED]
                atk_frs = [t for t in gmap.my_uships() if t.dist_to(atk_pos) <= MAX_SPEED+2]
                if len(atk_frs) > len(atk_ens):
                    if nav_cmd:
                        en_ship_assigned[e] -= 1
                        cmds.append(nav_cmd)
                    if move:
                        move_table[s] = move
                    unassigned.discard(s)
                    continue

                # OTHER OPTIONS
                en_dships = sorted(gmap.en_dships(),key=lambda t:s.dist_to(t))
예제 #13
0
def navigate(ship,
             target,
             game_map,
             speed,
             avoid_obstacles=True,
             max_corrections=90,
             angular_step=1,
             ignore_ships=False,
             ignore_planets=False,
             clockwise=True,
             iteration=0):
    """
    Move a ship to a specific target position (Entity). It is recommended to place the position
    itself here, else navigate will crash into the target. If avoid_obstacles is set to True (default)
    will avoid obstacles on the way, with up to max_corrections corrections. Note that each correction accounts
    for angular_step degrees difference, meaning that the algorithm will naively try max_correction degrees before giving
    up (and returning None). The navigation will only consist of up to one command; call this method again
    in the next turn to continue navigating to the position.

    :param Entity target: The entity to which you will navigate
    :param game_map.Map game_map: The map of the game, from which obstacles will be extracted
    :param int speed: The (max) speed to navigate. If the obstacle is nearer, will adjust accordingly.
    :param bool avoid_obstacles: Whether to avoid the obstacles in the way (simple pathfinding).
    :param int max_corrections: The maximum number of degrees to deviate per turn while trying to pathfind. If exceeded returns None.
    :param int angular_step: The degree difference to deviate if the original destination has obstacles
    :param bool ignore_ships: Whether to ignore ships in calkculations (this will make your movement faster, but more precarious)
    :param bool ignore_planets: Whether to ignore planets in calculations (useful if you want to crash onto planets)
    :return string: The command trying to be passed to the Halite engine or None if movement is not possible within max_corrections degrees.
    :rtype: str
    """
    # Assumes a position, not planet (as it would go to the center of the planet otherwise)
    if max_corrections <= 0:
        return 0, 0
    distance = ship.calculate_distance_between(target)
    angle = ship.calculate_angle_between(target)
    ignore = () if not (ignore_ships or ignore_planets) \
        else Ship if (ignore_ships and not ignore_planets) \
        else Planet if (ignore_planets and not ignore_ships) \
        else Entity
    if avoid_obstacles and game_map.obstacles_between(ship, target, ignore):
        iteration += 1
        if clockwise:
            new_angle = angle - iteration * angular_step
            clockwise = False
        else:
            new_angle = angle + iteration * angular_step
            clockwise = True

        new_target_dx = math.cos(math.radians(new_angle)) * distance
        new_target_dy = math.sin(math.radians(new_angle)) * distance
        new_target = Position(ship.x + new_target_dx, ship.y + new_target_dy)
        return navigate(ship,
                        new_target,
                        game_map,
                        speed,
                        True,
                        max_corrections - 1,
                        angular_step,
                        clockwise=clockwise,
                        iteration=iteration)
    speed = speed if (distance >= speed) else distance
    return speed, angle
예제 #14
0
    def _get_commands(self, action, world_map: hlt.game_map.Map):
        commands = []
        player_id = world_map.get_me().id
        planets = world_map.all_planets()
        all_ships = world_map._all_ships()
        ships = [ship for ship in all_ships if ship.owner.id == player_id]
        enemy_ships = [
            ship for ship in world_map._all_ships()
            if ship.owner.id != player_id
        ]

        free_planets = []
        enemy_planets = []
        enemy_ships_on_tile = []
        target_tile = floor(action)
        for planet in planets:
            planet_tile = self.grid.get_tile_id(planet.x, planet.y)
            if planet_tile == target_tile and not planet.is_owned():
                free_planets.append(planet)
            elif planet_tile == target_tile and planet.owner.id != player_id:
                enemy_planets.append(planet)

        tile_center_x, tile_center_y = self.grid.get_tile_center_by_id(
            target_tile)

        for ship in enemy_ships:
            ship_tile = self.grid.get_tile_id(ship.x, ship.y)
            if ship_tile == target_tile:
                enemy_ships_on_tile.append(ship)

        if len(free_planets) > 0:
            for ship in ships:
                dest_planet = free_planets[np.argmin([
                    np.linalg.norm((planet.x - ship.x, planet.y - ship.y))
                    for planet in free_planets
                ])]
                if ship.can_dock(dest_planet):
                    commands.append(ship.dock(dest_planet))
                else:
                    commands.append(
                        navigate(world_map,
                                 self.start_round,
                                 ship,
                                 ship.closest_point_to(dest_planet),
                                 speed=int(hlt.constants.MAX_SPEED / 2)))
        # elif len(enemy_ships_on_tile) > 0:
        #     for ship in ships:
        #         dest_ship = enemy_ships_on_tile[np.argmin([
        #             np.linalg.norm((enemy.x - ship.x, enemy.y - ship.y))
        #             for enemy in enemy_ships_on_tile
        #         ])]
        #         commands.append(attack(
        #             world_map,
        #             ship,
        #             Position(dest_ship.x, dest_ship.y),
        #             speed=int(hlt.constants.MAX_SPEED / 2)))
        elif len(enemy_planets) > 0:
            for ship in ships:
                dest_planet = enemy_planets[np.argmin([
                    np.linalg.norm((planet.x - ship.x, planet.y - ship.y))
                    for planet in enemy_planets
                ])]
                if len(dest_planet.all_docked_ships()) == 0:
                    if ship.can_dock(dest_planet):
                        commands.append(ship.dock(dest_planet))
                    else:
                        commands.append(
                            navigate(world_map,
                                     self.start_round,
                                     ship,
                                     ship.closest_point_to(dest_planet),
                                     speed=int(hlt.constants.MAX_SPEED / 2)))
                else:
                    weakest_ship = None
                    for s in dest_planet.all_docked_ships():
                        if weakest_ship is None or weakest_ship.health > s.health:
                            weakest_ship = s
                    commands.append(
                        navigate(world_map, self.start_round, ship,
                                 ship.closest_point_to(weakest_ship),
                                 int(hlt.constants.MAX_SPEED / 2)))

        else:
            for ship in ships:
                commands.append(
                    navigate(world_map,
                             self.start_round,
                             ship,
                             Position(tile_center_x, tile_center_y),
                             speed=int(hlt.constants.MAX_SPEED / 2)))

        return commands
예제 #15
0
    def compute_utility(self, x, y, ship, enemy_ships):
        planet_utilities, docked_ship_utilities, enemy_ship_utility = [0
                                                                       ], [0
                                                                           ], 0
        pos = Position(x, y)

        if self._hide:
            hiding_positions = [
                Position(3, 3),
                Position(self._game.map.width - 3, 3),
                Position(3, self._game.map.height - 3),
                Position(self._game.map.width - 3, self._game.map.height - 3)
            ]
            utility = 0

            for hiding_position in hiding_positions:
                utility += 1 / pos.calculate_distance_sq_between(
                    hiding_position)

            return utility

        for planet in self._game.map.all_planets():

            r = self.distance_to_planet(planet.id, x, y)
            if r == np.infty:
                continue

            r += 1

            planet_weight = 1 if self._num_players < 3 else self._planet_distance_from_center[
                planet.id]

            if not planet.is_owned() and self._should_i_dock:
                free_docking_spots = planet.num_docking_spots - planet.num_docked_ships(
                )
                planet_utilities.append(planet_weight * free_docking_spots *
                                        self._unowned_planet_weight / r**2)
            elif planet.owner == self._game.map.get_me(
            ) and not planet.is_full() and self._should_i_dock:
                planet_utilities.append(planet_weight *
                                        self._owned_planet_weight / r**2)
            elif planet.is_owned() and planet.owner != self._game.map.get_me():
                planet_utilities.append(planet_weight *
                                        self._enemy_planet_weight / r**2)

                if r < self._r_attack_docked:
                    angle_pos = planet.calculate_angle_between(pos)

                    docked_ship_utility = 0
                    for docked_ship in planet.all_docked_ships():
                        angle_ship = planet.calculate_angle_between(
                            docked_ship)
                        angle_diff = (angle_ship - angle_pos) % 360
                        angle_diff = min(angle_diff, 360 - angle_diff)
                        docked_ship_utility += 180 - angle_diff

                    docked_ship_utilities.append(docked_ship_utility)

        for enemy_ship in enemy_ships:
            enemy_ship_previous = self._game.map.get_player_previous(
                enemy_ship.owner.id).get_ship(enemy_ship.id)
            enemy_ship_previous = enemy_ship_previous if enemy_ship_previous else enemy_ship

            x, y = enemy_ship.x, enemy_ship.y
            dx = enemy_ship.x - enemy_ship_previous.x
            dy = enemy_ship.y - enemy_ship_previous.y
            theta = self._expected_enemy_theta
            expected_next_pos = Position(x + theta * dx, y + theta * dy)

            r2 = pos.calculate_distance_sq_between(expected_next_pos)
            if r2 < self._r2_chase_enemy:
                enemy_ship_utility += self._enemy_weight / r2

        return np.sum(planet_utilities) + max(
            docked_ship_utilities) + enemy_ship_utility
예제 #16
0
    def avoid_collision(self, ship, entity, collision):
        logging.info('Avoid Collision')
        logging.info(ship)
        logging.info(entity)
        logging.info(collision)

        # We want to modifiy how much the ship moves based on
        #   If the ship is close to the target, deviate less
        #   If the ship is going slow, deviate less (will not move if speed is 0)
        if ship.distance_to_target == 0 and entity.distance_to_target == 0:
            # They both reached their targets
            init_ship_modifier = (ship.magnitude / hlt.constants.MAX_SPEED)
            init_entity_modifier = (entity.magnitude / hlt.constants.MAX_SPEED)
        else:
            init_ship_modifier = (ship.magnitude / hlt.constants.MAX_SPEED) * \
                            (ship.distance_to_target / (ship.distance_to_target + entity.distance_to_target))

            init_entity_modifier = (entity.magnitude / hlt.constants.MAX_SPEED) * \
                              (entity.distance_to_target / (entity.distance_to_target + ship.distance_to_target))

        if init_ship_modifier == 0 and init_entity_modifier == 0:
            return  # They are already colliding...

        ship_modifier = init_ship_modifier / (init_ship_modifier +
                                              init_entity_modifier)
        entity_modifier = init_entity_modifier / (init_ship_modifier +
                                                  init_entity_modifier)

        logging.info('ship_modifer: {}   entity_modifer: {}'.format(
            ship_modifier, entity_modifier))

        if ship.magnitude == 0 and entity.magnitude == 0:
            raise (Exception('Both ships are not moving...'))

        # Note: By always taking the shortest path to something the rotation + distance modifier
        # should (almost) always keep the ship in range of the target

        # TODO: Check if the ships paths cross (below only works for co-liniar

        # Find where the collision first happened
        t = collision[3]
        ship_position = Position(ship.x + ship.vel_x * t,
                                 ship.y + ship.vel_y * t)
        entity_position = Position(entity.x + entity.vel_x * t,
                                   entity.y + entity.vel_y * t)

        logging.info(
            'collision happened at ship_position: {}   entity_position: {}'.
            format(ship_position, entity_position))

        # Work out the closest point they meet
        ship_velocity_step = Position(ship.vel_x / VELOCITY_STEPS,
                                      ship.vel_y / VELOCITY_STEPS)
        entity_velocity_step = Position(entity.vel_x / VELOCITY_STEPS,
                                        entity.vel_y / VELOCITY_STEPS)

        logging.info('velocity step ship: {}   entity: {}'.format(
            ship_velocity_step, entity_velocity_step))

        min_distance = math.inf
        velocity_step = None
        min_ship_position = None
        min_entity_position = None

        for step in range(VELOCITY_STEPS):
            current_ship_position = Position(
                ship_position.x + ship_velocity_step.x * step,
                ship_position.y + ship_velocity_step.y * step)
            current_entity_position = Position(
                entity_position.x + entity_velocity_step.x * step,
                entity_position.y + entity_velocity_step.y * step)

            distance = current_ship_position.calculate_distance_between(
                current_entity_position)
            if distance < min_distance:
                min_distance = distance
                velocity_step = step

                min_ship_position = current_ship_position
                min_entity_position = current_entity_position

        logging.info('min distance {}'.format(min_distance))

        # Required distance
        required_distance = ship.radius + entity.radius
        distance_to_deflect = required_distance - min_distance

        logging.info('required_distance {}, distance_to_reflect'.format(
            required_distance, distance_to_deflect))

        if ship.docking_status != ship.DockingStatus.UNDOCKED:
            logging.info('Ship is docked')
        elif ship.magnitude == 0:
            logging.info(
                'Entity is not moving atm (it may have just started to dock)')
        else:
            new_ship_angle = self.get_deflected_angle(
                ship, entity, distance_to_deflect * ship_modifier)
            ship.thrust(ship.magnitude, new_ship_angle)
            #logging.info('new_ship_angle {}, ship.magnitude'.format(ship.magnitude, new_ship_angle))

        if isinstance(entity, hlt.entity.Planet):
            logging.info('Entity is planet')
        elif entity.docking_status != entity.DockingStatus.UNDOCKED:
            logging.info('Entity is docked')
        elif entity.magnitude == 0:
            logging.info(
                'Entity is not moving atm (it may have just started to dock)')
        else:
            new_entity_angle = self.get_deflected_angle(
                entity, ship, distance_to_deflect * entity_modifier)
            entity.thrust(entity.magnitude, new_entity_angle)

            logging.info('new_entity_angle {}, entity.magnitude'.format(
                new_entity_angle, entity.magnitude))
예제 #17
0
# Then we print our start message to the logs
logging.info("Starting my Greedy bot!")

game_state = 0
first_turn = True

while True:
    # TURN START
    # Update the map for the new turn and get the latest version
    game_map = game.update_map()

    if first_turn == True:
        enemies = game_map.all_players()
        enemies.remove(game_map.get_me())

        centre_place = Position(0, 0)
        centre_place.x = game_map.get_me().all_ships()[0].x
        centre_place.y = game_map.get_me().all_ships()[0].y

        centre_enemy = Position(0, 0)
        for enemy in enemies:
            centre_enemy.x += enemy.all_ships()[0].x
            centre_enemy.y += enemy.all_ships()[0].y
        centre_enemy.x /= len(enemies)
        centre_enemy.y /= len(enemies)
        first_turn = False

    #logging.info("Centre.x: " + str(centre_place.x))
    #logging.info("Centre.y: " + str(centre_place.y))

    # Here we define the set of commands to be sent to the Halite engine at the end of the turn
예제 #18
0
    def compute_command_queue(self):

        my_ships = [ship for ship in self._game.map.get_me().all_ships()]
        my_docked_ships = [
            ship for ship in my_ships
            if ship.docking_status in (Ship.DockingStatus.DOCKED,
                                       Ship.DockingStatus.DOCKING,
                                       Ship.DockingStatus.UNDOCKING)
        ]
        my_undocked_ships = [
            ship for ship in my_ships
            if ship.docking_status == Ship.DockingStatus.UNDOCKED
        ]
        enemy_ships = [
            ship for player in self._game.map.all_players()
            if not player == self._game.map.get_me()
            for ship in player.all_ships()
        ]

        moves = []

        def no_collision(source: Entity, target: Entity):

            for s, t in moves:

                collision_possible = abs(source.x -
                                         s.x) < 15 and abs(source.y - s.y) < 15
                if collision_possible and min_r2(source, target, s, t) < 1.001:
                    return False

            return True

        for ship in my_docked_ships:
            moves.append((ship, ship))

        potential_new_positions_and_utilities = []

        free_docking_spots = {}
        for planet in self._game.map.all_planets():
            if not planet.is_owned() or planet.owner == self._game.map.get_me(
            ):
                free_docking_spots[
                    planet.
                    id] = planet.num_docking_spots - planet.num_docked_ships()
            else:
                free_docking_spots[planet.id] = 0

        for ship in my_undocked_ships:

            time_left = self.time_left()
            if time_left < 0.3:
                break

            potential_new_positions_and_utilities += self.compute_potential_new_positions_and_utilities(
                ship, enemy_ships)

        command_queue = []
        ships_moved = set()

        if self._should_i_undock:
            for ship in my_docked_ships:
                if ship.docking_status == Ship.DockingStatus.DOCKED:
                    command_queue.append(ship.undock())

        for utility, new_x, new_y, speed, angle, ship in sorted(
                potential_new_positions_and_utilities, key=first):

            time_left = self.time_left()
            if time_left < 0.2:
                return command_queue

            if ship not in ships_moved:
                for planet in self._game.map.all_planets():
                    if self._should_i_dock and free_docking_spots[
                            planet.id] > 0 and ship.can_dock(
                                planet) and no_collision(
                                    ship, ship) and self.no_enemy_close(
                                        ship, enemy_ships):
                        free_docking_spots[planet.id] -= 1
                        command_queue.append(ship.dock(planet))
                        ships_moved.add(ship)
                        moves.append((ship, ship))
                        # print('Ship {}: I''m docking'.format(ship.id))
                        break
                else:
                    new_position = Position(new_x, new_y)

                    if no_collision(
                            ship, new_position) and self.no_crash_into_planet(
                                ship, new_position):
                        command_queue.append(ship.thrust(speed, angle))
                        ships_moved.add(ship)
                        moves.append((ship, new_position))
                        # print('Ship {}: I''m moving to {} {} ({})'.format(ship.id, new_x, new_y, utility))

        return command_queue
예제 #19
0
             move_table[s] = move
     unassigned.discard(s)
 elif type(e) == hlt.entity.Ship:
     # WITHIN POTENTIAL ATTACK RANGE
     if s.dist_to(e) <= WEAPON_RADIUS + 2 * MAX_SPEED:
         if not doomed:
             # ATTACK
             if s in has_atked:
                 nav_cmd, move = helper.nav(s,
                                            s.closest_pt_to(e, 6),
                                            gmap, None, move_table)
             else:
                 nav_cmd, move = helper.nav(s, s.closest_pt_to(e),
                                            gmap, None, move_table)
             if move:
                 atk_pos = Position(move.p2)
             else:
                 atk_pos = Position(
                     s.loc,
                     s.loc + Point.polar(MAX_SPEED, s.angle_to(e)))
             atk_ens = [
                 t for t in gmap.en_uships()
                 if t.dist_to(atk_pos) <= WEAPON_RADIUS + MAX_SPEED
             ]
             atk_frs = [
                 t for t in gmap.my_uships()
                 if t.dist_to(atk_pos) <= MAX_SPEED + 2
             ]
             if len(atk_frs) > len(atk_ens):
                 if nav_cmd:
                     en_ship_assigned[e] -= 1