Ejemplo n.º 1
0
    def order_airlift_assets_at(self, control_point: ControlPoint) -> None:
        unclaimed_parking = control_point.unclaimed_parking(self.game)
        # Buy a maximum of unclaimed_parking only to prevent that aircraft procurement
        # take place at another base
        gap = min(
            [
                self.desired_airlift_capacity(control_point)
                - self.current_airlift_capacity(control_point),
                unclaimed_parking,
            ]
        )

        if gap <= 0:
            return

        if gap % 2:
            # Always buy in pairs since we're not trying to fill odd squadrons. Purely
            # aesthetic.
            gap += 1

        if gap > unclaimed_parking:
            # Prevent to buy more aircraft than possible
            return

        self.game.procurement_requests_for(player=control_point.captured).append(
            AircraftProcurementRequest(
                control_point, nautical_miles(200), FlightType.TRANSPORT, gap
            )
        )
Ejemplo n.º 2
0
    def _affordable_aircraft_for_task(
        self,
        task: FlightType,
        airbase: ControlPoint,
        number: int,
        max_price: float,
    ) -> Optional[AircraftType]:
        best_choice: Optional[AircraftType] = None
        for unit in aircraft_for_task(task):
            if unit not in self.faction.aircrafts:
                continue
            if unit.price * number > max_price:
                continue
            if not airbase.can_operate(unit):
                continue

            for squadron in self.air_wing.squadrons_for(unit):
                if task in squadron.auto_assignable_mission_types:
                    break
            else:
                continue

            # Affordable, compatible, and we have a squadron capable of the task. To
            # keep some variety, skip with a 50/50 chance. Might be a good idea to have
            # the chance to skip based on the price compared to the rest of the choices.
            best_choice = unit
            if random.choice([True, False]):
                break
        return best_choice
Ejemplo n.º 3
0
 def operates_from(self, control_point: ControlPoint) -> bool:
     if not control_point.can_operate(self.aircraft):
         return False
     if control_point.is_carrier:
         return self.operating_bases.carrier
     elif control_point.is_lha:
         return self.operating_bases.lha
     else:
         return self.operating_bases.shore
Ejemplo n.º 4
0
 def for_link(game: Game, a: ControlPoint, b: ControlPoint,
              points: list[Point], sea: bool) -> SupplyRouteJs:
     return SupplyRouteJs(
         points=[p.latlng() for p in points],
         front_active=not sea and a.front_is_active(b),
         is_sea=sea,
         blue=a.captured,
         active_transports=TransportFinder(
             game, a, b).describe_active_transports(sea),
     )
Ejemplo n.º 5
0
    def plan_relocation(self, destination: ControlPoint,
                        theater: ConflictTheater) -> None:
        if destination == self.location:
            logging.warning(
                f"Attempted to plan relocation of {self} to current location "
                f"{destination}. Ignoring.")
            return
        if destination == self.destination:
            logging.warning(
                f"Attempted to plan relocation of {self} to current destination "
                f"{destination}. Ignoring.")
            return

        if self.expected_size_next_turn > destination.unclaimed_parking():
            raise RuntimeError(
                f"Not enough parking for {self} at {destination}.")
        if not destination.can_operate(self.aircraft):
            raise RuntimeError(f"{self} cannot operate at {destination}.")
        self.destination = destination
        self.replan_ferry_flights(theater)
Ejemplo n.º 6
0
 def _affordable_aircraft_of_types(
         self, types: List[Type[FlyingType]], airbase: ControlPoint,
         number: int, max_price: int) -> Optional[Type[FlyingType]]:
     unit_pool = [u for u in self.faction.aircrafts if u in types]
     affordable_units = [
         u for u in unit_pool
         if db.PRICES[u] * number <= max_price and airbase.can_operate(u)
     ]
     if not affordable_units:
         return None
     return random.choice(affordable_units)
Ejemplo n.º 7
0
 def for_control_point(control_point: ControlPoint) -> ControlPointJs:
     destination = None
     if control_point.target_position is not None:
         destination = control_point.target_position.latlng()
     return ControlPointJs(
         id=control_point.id,
         name=control_point.name,
         blue=control_point.captured,
         position=control_point.position.latlng(),
         mobile=control_point.moveable and control_point.captured,
         destination=destination,
         sidc=str(control_point.sidc()),
     )
Ejemplo n.º 8
0
 def cost_ratio_of_ground_unit(self, control_point: ControlPoint,
                               unit_class: GroundUnitClass) -> float:
     allocations = control_point.allocated_ground_units(self.game.transfers)
     class_cost = 0
     total_cost = 0
     for unit_type, count in allocations.all.items():
         cost = unit_type.price * count
         total_cost += cost
         if unit_type.unit_class is unit_class:
             class_cost += cost
     if not total_cost:
         return 0
     return class_cost / total_cost
Ejemplo n.º 9
0
    def _affordable_aircraft_of_types(
            self, types: List[Type[FlyingType]], airbase: ControlPoint,
            number: int, max_price: float) -> Optional[Type[FlyingType]]:
        best_choice: Optional[Type[FlyingType]] = None
        for unit in [u for u in self.faction.aircrafts if u in types]:
            if db.PRICES[unit] * number > max_price:
                continue
            if not airbase.can_operate(unit):
                continue

            # Affordable and compatible. To keep some variety, skip with a 50/50
            # chance. Might be a good idea to have the chance to skip based on
            # the price compared to the rest of the choices.
            best_choice = unit
            if random.choice([True, False]):
                break
        return best_choice
    def generate_for_task(
            self, task: FlightType,
            control_point: ControlPoint) -> Optional[SquadronDef]:
        aircraft_choice: Optional[AircraftType] = None
        for aircraft in aircraft_for_task(task):
            if aircraft not in self.faction.aircrafts:
                continue
            if not control_point.can_operate(aircraft):
                continue
            aircraft_choice = aircraft
            # 50/50 chance to keep looking for an aircraft that isn't as far up the
            # priority list to maintain some unit variety.
            if random.choice([True, False]):
                break

        if aircraft_choice is None:
            return None
        return self.generate_for_aircraft(aircraft_choice)