Пример #1
0
 def closest_enemy_airbase(
         cls, location: ControlPoint,
         max_distance: Distance) -> Optional[ControlPoint]:
     airfields = ObjectiveDistanceCache.get_closest_airfields(location)
     for airfield in airfields.all_airfields_within(max_distance):
         if airfield.captured != location.captured:
             return airfield
     return None
Пример #2
0
    def on_load(self, game_still_initializing: bool = False) -> None:
        from .sim import GameUpdateEvents

        if not hasattr(self, "name_generator"):
            self.name_generator = naming.namegen
        # Hack: Replace the global name generator state with the state from the save
        # game.
        #
        # We need to persist this state so that names generated after game load don't
        # conflict with those generated before exit.
        naming.namegen = self.name_generator
        LuaPluginManager.load_settings(self.settings)
        ObjectiveDistanceCache.set_theater(self.theater)
        self.compute_unculled_zones()
        if not game_still_initializing:
            # We don't need to push events that happen during load. The UI will fully
            # reset when we're done.
            self.compute_threat_zones(GameUpdateEvents())
Пример #3
0
    def aircraft_retreat_destination(
        self, squadron: Squadron
    ) -> Optional[ControlPoint]:
        closest = ObjectiveDistanceCache.get_closest_airfields(self)
        max_retreat_distance = squadron.aircraft.max_mission_range
        # Skip the first airbase because that's the airbase we're retreating
        # from.
        airfields = list(closest.operational_airfields_within(max_retreat_distance))[1:]
        not_preferred: Optional[ControlPoint] = None
        overfull: list[ControlPoint] = []
        for airbase in airfields:
            if airbase.captured != self.captured:
                continue

            if airbase.unclaimed_parking() < squadron.owned_aircraft:
                if airbase.can_operate(squadron.aircraft):
                    overfull.append(airbase)
                continue

            if squadron.operates_from(airbase):
                # Has room, is a preferred base type for this squadron, and is the
                # closest choice. No need to keep looking.
                return airbase

            if not_preferred is None and airbase.can_operate(squadron.aircraft):
                # Has room and is capable of operating from this base, but it isn't
                # preferred. Remember this option and use it if we can't find a
                # preferred base type with room.
                not_preferred = airbase
        if not_preferred is not None:
            # It's not our best choice but the other choices don't have room for the
            # squadron and would lead to aircraft being captured.
            return not_preferred

        # No base was available with enough room. Find whichever base has the most room
        # available so we lose as little as possible. The overfull list is already
        # sorted by distance, and filtered for appropriate destinations.
        base_for_fewest_losses: Optional[ControlPoint] = None
        loss_count = math.inf
        for airbase in overfull:
            overflow = -(
                airbase.unclaimed_parking()
                - squadron.owned_aircraft
                - squadron.pending_deliveries
            )
            if overflow < loss_count:
                loss_count = overflow
                base_for_fewest_losses = airbase
        return base_for_fewest_losses
    def package_airfield(self) -> ControlPoint:
        # We'll always have a package, but if this is being planned via the UI
        # it could be the first flight in the package.
        if not self.package.flights:
            raise PlanningError(
                "Cannot determine source airfield for package with no flights")

        # The package airfield is either the flight's airfield (when there is no
        # package) or the closest airfield to the objective that is the
        # departure airfield for some flight in the package.
        cache = ObjectiveDistanceCache.get_closest_airfields(
            self.package.target)
        for airfield in cache.operational_airfields:
            for flight in self.package.flights:
                if flight.departure == airfield:
                    return airfield
        raise PlanningError(
            "Could not find any airfield assigned to this package")
Пример #5
0
    def create_package_for_airlift(self) -> None:
        distance_cache = ObjectiveDistanceCache.get_closest_airfields(
            self.transfer.position
        )
        air_wing = self.game.air_wing_for(self.for_player)
        for cp in distance_cache.closest_airfields:
            if cp.captured != self.for_player:
                continue

            squadrons = air_wing.auto_assignable_for_task_at(FlightType.TRANSPORT, cp)
            for squadron in squadrons:
                if self.compatible_with_mission(squadron.aircraft, cp):
                    while (
                        squadron.untasked_aircraft
                        and squadron.has_available_pilots
                        and self.transfer.transport is None
                    ):
                        self.create_airlift_flight(squadron)
        if self.package.flights:
            self.game.ato_for(self.for_player).add_package(self.package)
Пример #6
0
    def best_squadrons_for(self, location: MissionTarget, task: FlightType,
                           size: int, this_turn: bool) -> list[Squadron]:
        airfield_cache = ObjectiveDistanceCache.get_closest_airfields(location)
        best_aircraft = aircraft_for_task(task)
        ordered: list[Squadron] = []
        for control_point in airfield_cache.operational_airfields:
            if control_point.captured != self.player:
                continue
            capable_at_base = []
            for squadron in control_point.squadrons:
                if squadron.can_auto_assign_mission(location, task, size,
                                                    this_turn):
                    capable_at_base.append(squadron)

            ordered.extend(
                sorted(
                    capable_at_base,
                    key=lambda s: best_aircraft.index(s.aircraft),
                ))
        return ordered
Пример #7
0
 def closest_airfields_to(location: MissionTarget) -> ClosestAirfields:
     """Returns the closest airfields to the given location."""
     return ObjectiveDistanceCache.get_closest_airfields(location)