Fix some typing in preparation for pydcs types.

Not complete, but progress.
This commit is contained in:
Dan Albert 2021-07-08 22:50:55 -07:00
parent fb9a0fe833
commit 53f6a0b32b
30 changed files with 208 additions and 193 deletions

View File

@ -5,14 +5,14 @@ import inspect
import logging
from collections import defaultdict
from dataclasses import dataclass, field
from typing import Dict, Iterator, Optional, Set, Tuple, Union, cast
from typing import Dict, Iterator, Optional, Set, Tuple, Union, cast, Any
from dcs.unitgroup import FlyingGroup
from dcs.weapons_data import Weapons, weapon_ids
from game.dcs.aircrafttype import AircraftType
PydcsWeapon = Dict[str, Union[int, str]]
PydcsWeapon = Dict[str, Any]
PydcsWeaponAssignment = Tuple[int, PydcsWeapon]

View File

@ -106,7 +106,7 @@ class PatrolConfig:
@dataclass(frozen=True)
class AircraftType(UnitType[FlyingType]):
class AircraftType(UnitType[Type[FlyingType]]):
carrier_capable: bool
lha_capable: bool
always_keeps_gun: bool

View File

@ -15,7 +15,7 @@ from game.dcs.unittype import UnitType
@dataclass(frozen=True)
class GroundUnitType(UnitType[VehicleType]):
class GroundUnitType(UnitType[Type[VehicleType]]):
unit_class: Optional[GroundUnitClass]
spawn_weight: int

View File

@ -4,12 +4,12 @@ from typing import TypeVar, Generic, Type
from dcs.unittype import UnitType as DcsUnitType
DcsUnitTypeT = TypeVar("DcsUnitTypeT", bound=DcsUnitType)
DcsUnitTypeT = TypeVar("DcsUnitTypeT", bound=Type[DcsUnitType])
@dataclass(frozen=True)
class UnitType(Generic[DcsUnitTypeT]):
dcs_unit_type: Type[DcsUnitTypeT]
dcs_unit_type: DcsUnitTypeT
name: str
description: str
year_introduced: str

View File

@ -5,7 +5,6 @@ from typing import List, TYPE_CHECKING, Type
from dcs.mapping import Point
from dcs.task import Task
from dcs.unittype import VehicleType
from game import persistency
from game.debriefing import AirLosses, Debriefing

View File

@ -84,10 +84,10 @@ class Faction:
requirements: Dict[str, str] = field(default_factory=dict)
# possible aircraft carrier units
aircraft_carrier: List[Type[UnitType]] = field(default_factory=list)
aircraft_carrier: List[Type[ShipType]] = field(default_factory=list)
# possible helicopter carrier units
helicopter_carrier: List[Type[UnitType]] = field(default_factory=list)
helicopter_carrier: List[Type[ShipType]] = field(default_factory=list)
# Possible carrier names
carrier_names: List[str] = field(default_factory=list)

View File

@ -70,20 +70,6 @@ class Operation:
cls._setup_mission_coalitions()
cls.current_mission.options.load_from_dict(options_dict)
@classmethod
def conflicts(cls) -> Iterable[Conflict]:
assert cls.game
for frontline in cls.game.theater.conflicts():
yield Conflict(
cls.game.theater,
frontline,
cls.game.player_faction.name,
cls.game.enemy_faction.name,
cls.game.player_country,
cls.game.enemy_country,
frontline.position,
)
@classmethod
def air_conflict(cls) -> Conflict:
assert cls.game
@ -97,8 +83,8 @@ class Operation:
FrontLine(player_cp, enemy_cp),
cls.game.player_faction.name,
cls.game.enemy_faction.name,
cls.game.player_country,
cls.game.enemy_country,
cls.current_mission.country(cls.game.player_country),
cls.current_mission.country(cls.game.enemy_country),
mid_point,
)

View File

@ -2,8 +2,6 @@ import itertools
import logging
from typing import Any
from dcs.unit import UnitType as DcsUnitType
from game.dcs.aircrafttype import AircraftType
from game.dcs.groundunittype import GroundUnitType
from game.dcs.unittype import UnitType
@ -33,7 +31,7 @@ class Base:
total += unit_type.price * count
return total
def total_units_of_type(self, unit_type: UnitType[DcsUnitType]) -> int:
def total_units_of_type(self, unit_type: UnitType[Any]) -> int:
return sum(
[
c

View File

@ -545,7 +545,7 @@ class ConflictTheater:
def find_ground_objects_by_obj_name(
self, obj_name: str
) -> list[TheaterGroundObject]:
) -> list[TheaterGroundObject[Any]]:
found = []
for cp in self.controlpoints:
for g in cp.ground_objects:

View File

@ -43,6 +43,7 @@ from .missiontarget import MissionTarget
from .theatergroundobject import (
GenericCarrierGroundObject,
TheaterGroundObject,
NavalGroundObject,
)
from ..dcs.aircrafttype import AircraftType
from ..dcs.groundunittype import GroundUnitType
@ -298,7 +299,7 @@ class ControlPoint(MissionTarget, ABC):
self.id = cp_id
self.full_name = name
self.at = at
self.connected_objectives: List[TheaterGroundObject] = []
self.connected_objectives: List[TheaterGroundObject[Any]] = []
self.preset_locations = PresetLocations()
self.helipads: List[PointWithHeading] = []
@ -326,7 +327,7 @@ class ControlPoint(MissionTarget, ABC):
return f"<{self.__class__}: {self.name}>"
@property
def ground_objects(self) -> List[TheaterGroundObject]:
def ground_objects(self) -> List[TheaterGroundObject[Any]]:
return list(self.connected_objectives)
@property
@ -502,7 +503,7 @@ class ControlPoint(MissionTarget, ABC):
def find_ground_objects_by_obj_name(
self, obj_name: str
) -> list[TheaterGroundObject]:
) -> list[TheaterGroundObject[Any]]:
found = []
for g in self.ground_objects:
if g.obj_name == obj_name:
@ -881,9 +882,12 @@ class NavalControlPoint(ControlPoint, ABC):
def heading(self) -> int:
return 0 # TODO compute heading
def find_main_tgo(self) -> TheaterGroundObject:
def find_main_tgo(self) -> GenericCarrierGroundObject:
for g in self.ground_objects:
if g.dcs_identifier in ["CARRIER", "LHA"]:
if isinstance(g, GenericCarrierGroundObject) and g.dcs_identifier in [
"CARRIER",
"LHA",
]:
return g
raise RuntimeError(f"Found no carrier/LHA group for {self.name}")

View File

@ -2,12 +2,12 @@ from __future__ import annotations
import itertools
import logging
from typing import Iterator, List, TYPE_CHECKING, Union
from typing import Iterator, List, TYPE_CHECKING, Union, Generic, TypeVar, Any
from dcs.mapping import Point
from dcs.triggers import TriggerZone
from dcs.unit import Unit
from dcs.unitgroup import Group
from dcs.unitgroup import Group, ShipGroup, VehicleGroup
from dcs.unittype import VehicleType
from .. import db
@ -47,7 +47,10 @@ NAME_BY_CATEGORY = {
}
class TheaterGroundObject(MissionTarget):
GroupT = TypeVar("GroupT", bound=Group)
class TheaterGroundObject(MissionTarget, Generic[GroupT]):
def __init__(
self,
name: str,
@ -66,7 +69,7 @@ class TheaterGroundObject(MissionTarget):
self.control_point = control_point
self.dcs_identifier = dcs_identifier
self.sea_object = sea_object
self.groups: List[Group] = []
self.groups: List[GroupT] = []
@property
def is_dead(self) -> bool:
@ -206,7 +209,7 @@ class TheaterGroundObject(MissionTarget):
raise NotImplementedError
class BuildingGroundObject(TheaterGroundObject):
class BuildingGroundObject(TheaterGroundObject[VehicleGroup]):
def __init__(
self,
name: str,
@ -253,7 +256,7 @@ class BuildingGroundObject(TheaterGroundObject):
def kill(self) -> None:
self._dead = True
def iter_building_group(self) -> Iterator[TheaterGroundObject]:
def iter_building_group(self) -> Iterator[TheaterGroundObject[Any]]:
for tgo in self.control_point.ground_objects:
if tgo.obj_name == self.obj_name and not tgo.is_dead:
yield tgo
@ -338,7 +341,7 @@ class FactoryGroundObject(BuildingGroundObject):
)
class NavalGroundObject(TheaterGroundObject):
class NavalGroundObject(TheaterGroundObject[ShipGroup]):
def mission_types(self, for_player: bool) -> Iterator[FlightType]:
from gen.flights.flight import FlightType
@ -407,7 +410,7 @@ class LhaGroundObject(GenericCarrierGroundObject):
return f"{self.faction_color}|EWR|{super().group_name}"
class MissileSiteGroundObject(TheaterGroundObject):
class MissileSiteGroundObject(TheaterGroundObject[VehicleGroup]):
def __init__(
self, name: str, group_id: int, position: Point, control_point: ControlPoint
) -> None:
@ -431,7 +434,7 @@ class MissileSiteGroundObject(TheaterGroundObject):
return False
class CoastalSiteGroundObject(TheaterGroundObject):
class CoastalSiteGroundObject(TheaterGroundObject[VehicleGroup]):
def __init__(
self,
name: str,
@ -463,7 +466,7 @@ class CoastalSiteGroundObject(TheaterGroundObject):
# The SamGroundObject represents all type of AA
# The TGO can have multiple types of units (AAA,SAM,Support...)
# Differentiation can be made during generation with the airdefensegroupgenerator
class SamGroundObject(TheaterGroundObject):
class SamGroundObject(TheaterGroundObject[VehicleGroup]):
def __init__(
self,
name: str,
@ -535,7 +538,7 @@ class SamGroundObject(TheaterGroundObject):
return True
class VehicleGroupGroundObject(TheaterGroundObject):
class VehicleGroupGroundObject(TheaterGroundObject[VehicleGroup]):
def __init__(
self,
name: str,
@ -563,7 +566,7 @@ class VehicleGroupGroundObject(TheaterGroundObject):
return True
class EwrGroundObject(TheaterGroundObject):
class EwrGroundObject(TheaterGroundObject[VehicleGroup]):
def __init__(
self,
name: str,

View File

@ -30,16 +30,16 @@ class PendingUnitDeliveries:
self.destination = destination
# Maps unit type to order quantity.
self.units: dict[UnitType[DcsUnitType], int] = defaultdict(int)
self.units: dict[UnitType[Any], int] = defaultdict(int)
def __str__(self) -> str:
return f"Pending delivery to {self.destination}"
def order(self, units: dict[UnitType[DcsUnitType], int]) -> None:
def order(self, units: dict[UnitType[Any], int]) -> None:
for k, v in units.items():
self.units[k] += v
def sell(self, units: dict[UnitType[DcsUnitType], int]) -> None:
def sell(self, units: dict[UnitType[Any], int]) -> None:
for k, v in units.items():
self.units[k] -= v

View File

@ -2,7 +2,7 @@
import itertools
import math
from dataclasses import dataclass
from typing import Dict, Optional
from typing import Dict, Optional, Any
from dcs.unit import Unit
from dcs.unitgroup import FlyingGroup, Group, VehicleGroup
@ -29,7 +29,7 @@ class FrontLineUnit:
@dataclass(frozen=True)
class GroundObjectUnit:
ground_object: TheaterGroundObject
ground_object: TheaterGroundObject[Any]
group: Group
unit: Unit
@ -100,7 +100,7 @@ class UnitMap:
def add_ground_object_units(
self,
ground_object: TheaterGroundObject,
ground_object: TheaterGroundObject[Any],
persistence_group: Group,
miz_group: Group,
) -> None:

View File

@ -5,7 +5,7 @@ import random
from dataclasses import dataclass
from datetime import timedelta
from functools import cached_property
from typing import Dict, List, Optional, TYPE_CHECKING, Type, Union, Iterable
from typing import Dict, List, Optional, TYPE_CHECKING, Type, Union, Iterable, Any
from dcs import helicopters
from dcs.action import AITaskPush, ActivateGroup
@ -351,7 +351,7 @@ class AircraftConflictGenerator:
def _setup_group(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -537,7 +537,7 @@ class AircraftConflictGenerator:
def _add_radio_waypoint(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
position: Point,
altitude: Distance,
airspeed: int = 600,
@ -548,7 +548,7 @@ class AircraftConflictGenerator:
def _rtb_for(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
cp: ControlPoint,
at: Optional[db.StartingPosition] = None,
) -> MovingPoint:
@ -680,7 +680,7 @@ class AircraftConflictGenerator:
self.unit_map.add_aircraft(group, flight)
def set_activation_time(
self, flight: Flight, group: FlyingGroup, delay: timedelta
self, flight: Flight, group: FlyingGroup[Any], delay: timedelta
) -> None:
# Note: Late activation causes the waypoint TOTs to look *weird* in the
# mission editor. Waypoint times will be relative to the group
@ -699,7 +699,7 @@ class AircraftConflictGenerator:
self.m.triggerrules.triggers.append(activation_trigger)
def set_startup_time(
self, flight: Flight, group: FlyingGroup, delay: timedelta
self, flight: Flight, group: FlyingGroup[Any], delay: timedelta
) -> None:
# Uncontrolled causes the AI unit to spawn, but not begin startup.
group.uncontrolled = True
@ -775,7 +775,7 @@ class AircraftConflictGenerator:
@staticmethod
def set_reduced_fuel(
flight: Flight, group: FlyingGroup, unit_type: Type[PlaneType]
flight: Flight, group: FlyingGroup[Any], unit_type: Type[PlaneType]
) -> None:
if unit_type is Su_33:
for unit in group.units:
@ -801,7 +801,7 @@ class AircraftConflictGenerator:
def configure_behavior(
self,
flight: Flight,
group: FlyingGroup,
group: FlyingGroup[Any],
react_on_threat: Optional[OptReactOnThreat.Values] = None,
roe: Optional[OptROE.Values] = None,
rtb_winchester: Optional[OptRTBOnOutOfAmmo.Values] = None,
@ -834,13 +834,13 @@ class AircraftConflictGenerator:
# https://forums.eagle.ru/forum/english/digital-combat-simulator/dcs-world-2-5/bugs-and-problems-ai/ai-ad/7121294-ai-stuck-at-high-aoa-after-making-sharp-turn-if-afterburner-is-restricted
@staticmethod
def configure_eplrs(group: FlyingGroup, flight: Flight) -> None:
def configure_eplrs(group: FlyingGroup[Any], flight: Flight) -> None:
if flight.unit_type.eplrs_capable:
group.points[0].tasks.append(EPLRS(group.id))
def configure_cap(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -857,7 +857,7 @@ class AircraftConflictGenerator:
def configure_sweep(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -874,7 +874,7 @@ class AircraftConflictGenerator:
def configure_cas(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -892,7 +892,7 @@ class AircraftConflictGenerator:
def configure_dead(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -917,7 +917,7 @@ class AircraftConflictGenerator:
def configure_sead(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -941,7 +941,7 @@ class AircraftConflictGenerator:
def configure_strike(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -959,7 +959,7 @@ class AircraftConflictGenerator:
def configure_anti_ship(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -977,7 +977,7 @@ class AircraftConflictGenerator:
def configure_runway_attack(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -995,7 +995,7 @@ class AircraftConflictGenerator:
def configure_oca_strike(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1012,7 +1012,7 @@ class AircraftConflictGenerator:
def configure_awacs(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1040,7 +1040,7 @@ class AircraftConflictGenerator:
def configure_refueling(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1066,7 +1066,7 @@ class AircraftConflictGenerator:
def configure_escort(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1082,7 +1082,7 @@ class AircraftConflictGenerator:
def configure_sead_escort(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1105,7 +1105,7 @@ class AircraftConflictGenerator:
def configure_transport(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1120,13 +1120,13 @@ class AircraftConflictGenerator:
restrict_jettison=True,
)
def configure_unknown_task(self, group: FlyingGroup, flight: Flight) -> None:
def configure_unknown_task(self, group: FlyingGroup[Any], flight: Flight) -> None:
logging.error(f"Unhandled flight type: {flight.flight_type}")
self.configure_behavior(flight, group)
def setup_flight_group(
self,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
dynamic_runways: Dict[str, RunwayData],
@ -1170,7 +1170,7 @@ class AircraftConflictGenerator:
self.configure_eplrs(group, flight)
def create_waypoints(
self, group: FlyingGroup, package: Package, flight: Flight
self, group: FlyingGroup[Any], package: Package, flight: Flight
) -> None:
for waypoint in flight.points:
@ -1238,7 +1238,7 @@ class AircraftConflictGenerator:
waypoint: FlightWaypoint,
package: Package,
flight: Flight,
group: FlyingGroup,
group: FlyingGroup[Any],
) -> None:
estimator = TotEstimator(package)
start_time = estimator.mission_start_time(flight)
@ -1281,7 +1281,7 @@ class PydcsWaypointBuilder:
def __init__(
self,
waypoint: FlightWaypoint,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
mission: Mission,
@ -1324,7 +1324,7 @@ class PydcsWaypointBuilder:
def for_waypoint(
cls,
waypoint: FlightWaypoint,
group: FlyingGroup,
group: FlyingGroup[Any],
package: Package,
flight: Flight,
mission: Mission,

View File

@ -1,13 +1,12 @@
from dcs.unitgroup import VehicleGroup
from dcs.vehicles import MissilesSS, Unarmed, AirDefence
from game import Game
from game.factions.faction import Faction
from game.theater.theatergroundobject import CoastalSiteGroundObject
from gen.sam.group_generator import GroupGenerator
from gen.sam.group_generator import VehicleGroupGenerator
class SilkwormGenerator(GroupGenerator[VehicleGroup]):
class SilkwormGenerator(VehicleGroupGenerator[CoastalSiteGroundObject]):
def __init__(
self, game: Game, ground_object: CoastalSiteGroundObject, faction: Faction
) -> None:

View File

@ -1,14 +1,12 @@
import random
from dcs.unitgroup import VehicleGroup
from game import Game
from game.dcs.groundunittype import GroundUnitType
from game.theater.theatergroundobject import VehicleGroupGroundObject
from gen.sam.group_generator import GroupGenerator
from gen.sam.group_generator import VehicleGroupGenerator
class ArmoredGroupGenerator(GroupGenerator[VehicleGroup]):
class ArmoredGroupGenerator(VehicleGroupGenerator[VehicleGroupGroundObject]):
def __init__(
self,
game: Game,
@ -37,7 +35,7 @@ class ArmoredGroupGenerator(GroupGenerator[VehicleGroup]):
)
class FixedSizeArmorGroupGenerator(GroupGenerator[VehicleGroup]):
class FixedSizeArmorGroupGenerator(VehicleGroupGenerator[VehicleGroupGroundObject]):
def __init__(
self,
game: Game,

View File

@ -3,7 +3,6 @@ from __future__ import annotations
import random
from typing import TYPE_CHECKING
from dcs.ships import (
Type_052C,
Type_052B,
@ -11,9 +10,9 @@ from dcs.ships import (
)
from game.factions.faction import Faction
from game.theater.theatergroundobject import ShipGroundObject
from gen.fleet.dd_group import DDGroupGenerator
from gen.sam.group_generator import ShipGroupGenerator
from game.theater.theatergroundobject import TheaterGroundObject
if TYPE_CHECKING:
from game.game import Game
@ -65,9 +64,7 @@ class ChineseNavyGroupGenerator(ShipGroupGenerator):
class Type54GroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(Type54GroupGenerator, self).__init__(
game, ground_object, faction, Type_054A
)

View File

@ -1,12 +1,13 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Type
from game.factions.faction import Faction
from game.theater.theatergroundobject import TheaterGroundObject
from gen.sam.group_generator import ShipGroupGenerator
from dcs.unittype import ShipType
from dcs.ships import PERRY, USS_Arleigh_Burke_IIa
from dcs.unittype import ShipType
from game.factions.faction import Faction
from game.theater.theatergroundobject import ShipGroundObject
from gen.sam.group_generator import ShipGroupGenerator
if TYPE_CHECKING:
from game.game import Game
@ -16,7 +17,7 @@ class DDGroupGenerator(ShipGroupGenerator):
def __init__(
self,
game: Game,
ground_object: TheaterGroundObject,
ground_object: ShipGroundObject,
faction: Faction,
ddtype: Type[ShipType],
):
@ -42,18 +43,14 @@ class DDGroupGenerator(ShipGroupGenerator):
class OliverHazardPerryGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(OliverHazardPerryGroupGenerator, self).__init__(
game, ground_object, faction, PERRY
)
class ArleighBurkeGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(ArleighBurkeGroupGenerator, self).__init__(
game, ground_object, faction, USS_Arleigh_Burke_IIa
)

View File

@ -2,14 +2,12 @@ from dcs.ships import La_Combattante_II
from game import Game
from game.factions.faction import Faction
from game.theater import TheaterGroundObject
from game.theater.theatergroundobject import ShipGroundObject
from gen.fleet.dd_group import DDGroupGenerator
class LaCombattanteIIGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(LaCombattanteIIGroupGenerator, self).__init__(
game, ground_object, faction, La_Combattante_II
)

View File

@ -1,4 +1,5 @@
from __future__ import annotations
import random
from typing import TYPE_CHECKING
@ -12,11 +13,10 @@ from dcs.ships import (
SOM,
)
from game.factions.faction import Faction
from game.theater.theatergroundobject import ShipGroundObject
from gen.fleet.dd_group import DDGroupGenerator
from gen.sam.group_generator import ShipGroupGenerator
from game.factions.faction import Faction
from game.theater.theatergroundobject import TheaterGroundObject
if TYPE_CHECKING:
from game.game import Game
@ -85,32 +85,24 @@ class RussianNavyGroupGenerator(ShipGroupGenerator):
class GrishaGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(GrishaGroupGenerator, self).__init__(
game, ground_object, faction, ALBATROS
)
class MolniyaGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(MolniyaGroupGenerator, self).__init__(
game, ground_object, faction, MOLNIYA
)
class KiloSubGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(KiloSubGroupGenerator, self).__init__(game, ground_object, faction, KILO)
class TangoSubGroupGenerator(DDGroupGenerator):
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
def __init__(self, game: Game, ground_object: ShipGroundObject, faction: Faction):
super(TangoSubGroupGenerator, self).__init__(game, ground_object, faction, SOM)

View File

@ -18,6 +18,7 @@ from typing import (
TYPE_CHECKING,
Tuple,
TypeVar,
Any,
)
from game.dcs.aircrafttype import AircraftType
@ -284,7 +285,7 @@ class ObjectiveFinder:
self.game = game
self.is_player = is_player
def enemy_air_defenses(self) -> Iterator[tuple[TheaterGroundObject, Distance]]:
def enemy_air_defenses(self) -> Iterator[tuple[TheaterGroundObject[Any], Distance]]:
"""Iterates over all enemy SAM sites."""
doctrine = self.game.faction_for(self.is_player).doctrine
threat_zones = self.game.threat_zone_for(not self.is_player)
@ -314,14 +315,14 @@ class ObjectiveFinder:
yield ground_object, target_range
def threatening_air_defenses(self) -> Iterator[TheaterGroundObject]:
def threatening_air_defenses(self) -> Iterator[TheaterGroundObject[Any]]:
"""Iterates over enemy SAMs in threat range of friendly control points.
SAM sites are sorted by their closest proximity to any friendly control
point (airfield or fleet).
"""
target_ranges: list[tuple[TheaterGroundObject, Distance]] = []
target_ranges: list[tuple[TheaterGroundObject[Any], Distance]] = []
for target, threat_range in self.enemy_air_defenses():
ranges: list[Distance] = []
for cp in self.friendly_control_points():
@ -385,13 +386,13 @@ class ObjectiveFinder:
for target, _range in target_ranges:
yield target
def strike_targets(self) -> Iterator[TheaterGroundObject]:
def strike_targets(self) -> Iterator[TheaterGroundObject[Any]]:
"""Iterates over enemy strike targets.
Targets are sorted by their closest proximity to any friendly control
point (airfield or fleet).
"""
targets: List[Tuple[TheaterGroundObject, int]] = []
targets: List[Tuple[TheaterGroundObject[Any], int]] = []
# Building objectives are made of several individual TGOs (one per
# building).
found_targets: Set[str] = set()

View File

@ -1130,7 +1130,7 @@ class FlightPlanBuilder:
)
@staticmethod
def anti_ship_targets_for_tgo(tgo: TheaterGroundObject) -> List[StrikeTarget]:
def anti_ship_targets_for_tgo(tgo: NavalGroundObject) -> List[StrikeTarget]:
return [StrikeTarget(f"{g.name} at {tgo.name}", g) for g in tgo.groups]
def generate_anti_ship(self, flight: Flight) -> StrikeFlightPlan:

View File

@ -10,6 +10,7 @@ from typing import (
TYPE_CHECKING,
Tuple,
Union,
Any,
)
from dcs.mapping import Point
@ -33,7 +34,9 @@ from .flight import Flight, FlightWaypoint, FlightWaypointType
@dataclass(frozen=True)
class StrikeTarget:
name: str
target: Union[VehicleGroup, TheaterGroundObject, Unit, Group, MultiGroupTransport]
target: Union[
VehicleGroup, TheaterGroundObject[Any], Unit, Group, MultiGroupTransport
]
class WaypointBuilder:

View File

@ -9,7 +9,17 @@ from __future__ import annotations
import logging
import random
from typing import Dict, Iterator, Optional, TYPE_CHECKING, Type, List
from typing import (
Dict,
Iterator,
Optional,
TYPE_CHECKING,
Type,
List,
TypeVar,
Any,
Generic,
)
from dcs import Mission, Point, unitgroup
from dcs.action import SceneryDestructionZone
@ -56,7 +66,10 @@ FARP_FRONTLINE_DISTANCE = 10000
AA_CP_MIN_DISTANCE = 40000
class GenericGroundObjectGenerator:
TgoT = TypeVar("TgoT", bound=TheaterGroundObject[Any])
class GenericGroundObjectGenerator(Generic[TgoT]):
"""An unspecialized ground object generator.
Currently used only for SAM
@ -64,7 +77,7 @@ class GenericGroundObjectGenerator:
def __init__(
self,
ground_object: TheaterGroundObject,
ground_object: TgoT,
country: Country,
game: Game,
mission: Mission,
@ -133,7 +146,7 @@ class GenericGroundObjectGenerator:
)
class MissileSiteGenerator(GenericGroundObjectGenerator):
class MissileSiteGenerator(GenericGroundObjectGenerator[MissileSiteGroundObject]):
@property
def culled(self) -> bool:
# Don't cull missile sites - their range is long enough to make them easily
@ -196,7 +209,7 @@ class MissileSiteGenerator(GenericGroundObjectGenerator):
return site_range
class BuildingSiteGenerator(GenericGroundObjectGenerator):
class BuildingSiteGenerator(GenericGroundObjectGenerator[BuildingGroundObject]):
"""Generator for building sites.
Building sites are the primary type of non-airbase objective locations that
@ -324,7 +337,7 @@ class SceneryGenerator(BuildingSiteGenerator):
self.unit_map.add_scenery(scenery)
class GenericCarrierGenerator(GenericGroundObjectGenerator):
class GenericCarrierGenerator(GenericGroundObjectGenerator[GenericCarrierGroundObject]):
"""Base type for carrier group generation.
Used by both CV(N) groups and LHA groups.
@ -518,7 +531,7 @@ class LhaGenerator(GenericCarrierGenerator):
)
class ShipObjectGenerator(GenericGroundObjectGenerator):
class ShipObjectGenerator(GenericGroundObjectGenerator[ShipGroundObject]):
"""Generator for non-carrier naval groups."""
def generate(self) -> None:
@ -637,7 +650,7 @@ class GroundObjectsGenerator:
).generate()
for ground_object in cp.ground_objects:
generator: GenericGroundObjectGenerator
generator: GenericGroundObjectGenerator[Any]
if isinstance(ground_object, FactoryGroundObject):
generator = FactoryGenerator(
ground_object, country, self.game, self.m, self.unit_map

View File

@ -1,15 +1,14 @@
import random
from dcs.unitgroup import VehicleGroup
from dcs.vehicles import Unarmed, MissilesSS, AirDefence
from game import Game
from game.factions.faction import Faction
from game.theater.theatergroundobject import MissileSiteGroundObject
from gen.sam.group_generator import GroupGenerator
from gen.sam.group_generator import VehicleGroupGenerator
class ScudGenerator(GroupGenerator[VehicleGroup]):
class ScudGenerator(VehicleGroupGenerator[MissileSiteGroundObject]):
def __init__(
self, game: Game, ground_object: MissileSiteGroundObject, faction: Faction
) -> None:

View File

@ -1,15 +1,14 @@
import random
from dcs.unitgroup import VehicleGroup
from dcs.vehicles import Unarmed, MissilesSS, AirDefence
from game import Game
from game.factions.faction import Faction
from game.theater.theatergroundobject import MissileSiteGroundObject
from gen.sam.group_generator import GroupGenerator
from gen.sam.group_generator import VehicleGroupGenerator
class V1GroupGenerator(GroupGenerator[VehicleGroup]):
class V1GroupGenerator(VehicleGroupGenerator[MissileSiteGroundObject]):
def __init__(
self, game: Game, ground_object: MissileSiteGroundObject, faction: Faction
) -> None:

View File

@ -8,7 +8,7 @@ from dcs.unitgroup import VehicleGroup
from game import Game
from game.theater.theatergroundobject import SamGroundObject
from gen.sam.group_generator import GroupGenerator
from gen.sam.group_generator import VehicleGroupGenerator
class SkynetRole(Enum):
@ -38,7 +38,7 @@ class AirDefenseRange(Enum):
self.default_role = default_role
class AirDefenseGroupGenerator(GroupGenerator[VehicleGroup], ABC):
class AirDefenseGroupGenerator(VehicleGroupGenerator[SamGroundObject], ABC):
"""
This is the base for all SAM group generators
"""

View File

@ -1,13 +1,13 @@
from typing import Type
from dcs.unitgroup import VehicleGroup
from dcs.vehicles import AirDefence
from dcs.unittype import VehicleType
from dcs.vehicles import AirDefence
from gen.sam.group_generator import GroupGenerator
from game.theater.theatergroundobject import EwrGroundObject
from gen.sam.group_generator import VehicleGroupGenerator
class EwrGenerator(GroupGenerator[VehicleGroup]):
class EwrGenerator(VehicleGroupGenerator[EwrGroundObject]):
unit_type: Type[VehicleType]
@classmethod

View File

@ -4,24 +4,27 @@ import logging
import math
import random
from collections import Iterable
from typing import TYPE_CHECKING, Type, TypeVar, Generic
from typing import TYPE_CHECKING, Type, TypeVar, Generic, Any
from dcs import unitgroup
from dcs.mapping import Point
from dcs.point import PointAction
from dcs.unit import Ship, Vehicle
from dcs.unitgroup import MovingGroup, ShipGroup
from dcs.unittype import VehicleType, UnitType
from dcs.unit import Ship, Vehicle, Unit
from dcs.unitgroup import ShipGroup, VehicleGroup
from dcs.unittype import VehicleType, UnitType, ShipType
from game.dcs.groundunittype import GroundUnitType
from game.factions.faction import Faction
from game.theater.theatergroundobject import TheaterGroundObject
from game.theater.theatergroundobject import TheaterGroundObject, NavalGroundObject
if TYPE_CHECKING:
from game.game import Game
GroupType = TypeVar("GroupType", bound=MovingGroup)
GroupT = TypeVar("GroupT", VehicleGroup, ShipGroup)
UnitT = TypeVar("UnitT", bound=Unit)
UnitTypeT = TypeVar("UnitTypeT", bound=Type[UnitType])
TgoT = TypeVar("TgoT", bound=TheaterGroundObject[Any])
# TODO: Generate a group description rather than a pydcs group.
@ -29,41 +32,62 @@ GroupType = TypeVar("GroupType", bound=MovingGroup)
# groundobjectsgen for an example). We can do less work and include the data we
# care about in the format we want if we just generate our own group description
# types rather than pydcs groups.
class GroupGenerator(Generic[GroupType]):
price: int
def __init__(self, game: Game, ground_object: TheaterGroundObject) -> None:
class GroupGenerator(Generic[GroupT, UnitT, UnitTypeT, TgoT]):
def __init__(self, game: Game, ground_object: TgoT, group: GroupT) -> None:
self.game = game
self.go = ground_object
self.position = ground_object.position
self.heading = random.randint(0, 359)
self.price = 0
self.vg = unitgroup.VehicleGroup(self.game.next_group_id(), self.go.group_name)
wp = self.vg.add_waypoint(self.position, PointAction.OffRoad, 0)
wp.ETA_locked = True
self.vg: GroupT = group
def generate(self) -> None:
raise NotImplementedError
def get_generated_group(self) -> GroupType:
def get_generated_group(self) -> GroupT:
return self.vg
def add_unit(
self,
unit_type: Type[VehicleType],
unit_type: UnitTypeT,
name: str,
pos_x: float,
pos_y: float,
heading: int,
) -> Vehicle:
) -> UnitT:
return self.add_unit_to_group(
self.vg, unit_type, name, Point(pos_x, pos_y), heading
)
def add_unit_to_group(
self,
group: GroupType,
group: GroupT,
unit_type: UnitTypeT,
name: str,
position: Point,
heading: int,
) -> UnitT:
raise NotImplementedError
class VehicleGroupGenerator(
Generic[TgoT], GroupGenerator[VehicleGroup, Vehicle, Type[VehicleType], TgoT]
):
def __init__(self, game: Game, ground_object: TgoT) -> None:
super().__init__(
game,
ground_object,
unitgroup.VehicleGroup(self.game.next_group_id(), self.go.group_name),
)
wp = self.vg.add_waypoint(self.position, PointAction.OffRoad, 0)
wp.ETA_locked = True
def generate(self) -> None:
raise NotImplementedError
def add_unit_to_group(
self,
group: VehicleGroup,
unit_type: Type[VehicleType],
name: str,
position: Point,
@ -124,32 +148,34 @@ class GroupGenerator(Generic[GroupType]):
return positions
class ShipGroupGenerator(GroupGenerator[ShipGroup]):
class ShipGroupGenerator(
GroupGenerator[ShipGroup, Ship, Type[ShipType], NavalGroundObject]
):
"""Abstract class for other ship generator classes"""
def __init__(
self, game: Game, ground_object: TheaterGroundObject, faction: Faction
):
self.game = game
self.go = ground_object
self.position = ground_object.position
self.heading = random.randint(0, 359)
def __init__(self, game: Game, ground_object: NavalGroundObject, faction: Faction):
super().__init__(
game,
ground_object,
unitgroup.ShipGroup(self.game.next_group_id(), self.go.group_name),
)
self.faction = faction
self.vg = unitgroup.ShipGroup(self.game.next_group_id(), self.go.group_name)
wp = self.vg.add_waypoint(self.position, 0)
wp.ETA_locked = True
def add_unit(
def generate(self) -> None:
raise NotImplementedError
def add_unit_to_group(
self,
unit_type: Type[UnitType],
group: ShipGroup,
unit_type: Type[ShipType],
name: str,
pos_x: float,
pos_y: float,
position: Point,
heading: int,
) -> Ship:
unit = Ship(self.game.next_unit_id(), f"{self.go.group_name}|{name}", unit_type)
unit.position.x = pos_x
unit.position.y = pos_y
unit.position = position
unit.heading = heading
self.vg.add_unit(unit)
group.add_unit(unit)
return unit

View File

@ -1,4 +1,7 @@
from typing import Type
from dcs.mapping import Point
from dcs.unittype import VehicleType
from dcs.vehicles import AirDefence
from game import Game
@ -20,13 +23,13 @@ class SA10Generator(AirDefenseGroupGenerator):
def __init__(self, game: Game, ground_object: SamGroundObject):
super().__init__(game, ground_object)
self.sr1 = AirDefence.S_300PS_40B6MD_sr
self.sr2 = AirDefence.S_300PS_64H6E_sr
self.cp = AirDefence.S_300PS_54K6_cp
self.tr1 = AirDefence.S_300PS_40B6M_tr
self.tr2 = AirDefence.S_300PS_40B6M_tr
self.ln1 = AirDefence.S_300PS_5P85C_ln
self.ln2 = AirDefence.S_300PS_5P85D_ln
self.sr1: Type[VehicleType] = AirDefence.S_300PS_40B6MD_sr
self.sr2: Type[VehicleType] = AirDefence.S_300PS_64H6E_sr
self.cp: Type[VehicleType] = AirDefence.S_300PS_54K6_cp
self.tr1: Type[VehicleType] = AirDefence.S_300PS_40B6M_tr
self.tr2: Type[VehicleType] = AirDefence.S_300PS_40B6M_tr
self.ln1: Type[VehicleType] = AirDefence.S_300PS_5P85C_ln
self.ln2: Type[VehicleType] = AirDefence.S_300PS_5P85D_ln
def generate(self) -> None:
# Search Radar