mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Plan anti-ship missions automatically.
This commit is contained in:
parent
2ac92a75a4
commit
69dbe62b70
@ -5,7 +5,16 @@ import operator
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple, Type
|
||||
from typing import (
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
Set,
|
||||
TYPE_CHECKING,
|
||||
Tuple,
|
||||
Type,
|
||||
)
|
||||
|
||||
from dcs.unittype import FlyingType, UnitType
|
||||
|
||||
@ -16,6 +25,8 @@ from game.utils import nm_to_meter
|
||||
from gen import Conflict
|
||||
from gen.ato import Package
|
||||
from gen.flights.ai_flight_planner_db import (
|
||||
ANTISHIP_CAPABLE,
|
||||
ANTISHIP_PREFERRED,
|
||||
CAP_CAPABLE,
|
||||
CAP_PREFERRED,
|
||||
CAS_CAPABLE,
|
||||
@ -46,7 +57,7 @@ from theater import (
|
||||
# Avoid importing some types that cause circular imports unless type checking.
|
||||
from theater.theatergroundobject import (
|
||||
EwrGroundObject,
|
||||
VehicleGroupGroundObject,
|
||||
NavalGroundObject, VehicleGroupGroundObject,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -141,6 +152,8 @@ class AircraftAllocator:
|
||||
cap_missions = (FlightType.BARCAP, FlightType.TARCAP)
|
||||
if task in cap_missions:
|
||||
return CAP_PREFERRED
|
||||
elif task == FlightType.ANTISHIP:
|
||||
return ANTISHIP_PREFERRED
|
||||
elif task == FlightType.BAI:
|
||||
return CAS_CAPABLE
|
||||
elif task == FlightType.CAS:
|
||||
@ -159,6 +172,8 @@ class AircraftAllocator:
|
||||
cap_missions = (FlightType.BARCAP, FlightType.TARCAP)
|
||||
if task in cap_missions:
|
||||
return CAP_CAPABLE
|
||||
elif task == FlightType.ANTISHIP:
|
||||
return ANTISHIP_CAPABLE
|
||||
elif task == FlightType.BAI:
|
||||
return CAS_CAPABLE
|
||||
elif task == FlightType.CAS:
|
||||
@ -279,22 +294,10 @@ class ObjectiveFinder:
|
||||
SAM sites are sorted by their closest proximity to any friendly control
|
||||
point (airfield or fleet).
|
||||
"""
|
||||
sams: List[Tuple[TheaterGroundObject, int]] = []
|
||||
for sam in self.enemy_sams():
|
||||
ranges: List[int] = []
|
||||
for cp in self.friendly_control_points():
|
||||
ranges.append(sam.distance_to(cp))
|
||||
sams.append((sam, min(ranges)))
|
||||
|
||||
sams = sorted(sams, key=operator.itemgetter(1))
|
||||
for sam, _range in sams:
|
||||
yield sam
|
||||
return self._targets_by_range(self.enemy_sams())
|
||||
|
||||
def enemy_vehicle_groups(self) -> Iterator[VehicleGroupGroundObject]:
|
||||
"""Iterates over all enemy vehicle groups."""
|
||||
# Control points might have the same ground object several times, for
|
||||
# some reason.
|
||||
found_targets: Set[str] = set()
|
||||
for cp in self.enemy_control_points():
|
||||
for ground_object in cp.ground_objects:
|
||||
if not isinstance(ground_object, VehicleGroupGroundObject):
|
||||
@ -303,11 +306,7 @@ class ObjectiveFinder:
|
||||
if ground_object.is_dead:
|
||||
continue
|
||||
|
||||
if ground_object.name in found_targets:
|
||||
continue
|
||||
|
||||
yield ground_object
|
||||
found_targets.add(ground_object.name)
|
||||
|
||||
def threatening_vehicle_groups(self) -> Iterator[TheaterGroundObject]:
|
||||
"""Iterates over enemy vehicle groups near friendly control points.
|
||||
@ -315,16 +314,40 @@ class ObjectiveFinder:
|
||||
Groups are sorted by their closest proximity to any friendly control
|
||||
point (airfield or fleet).
|
||||
"""
|
||||
groups: List[Tuple[VehicleGroupGroundObject, int]] = []
|
||||
for group in self.enemy_vehicle_groups():
|
||||
return self._targets_by_range(self.enemy_vehicle_groups())
|
||||
|
||||
def enemy_ships(self) -> Iterator[NavalGroundObject]:
|
||||
for cp in self.enemy_control_points():
|
||||
for ground_object in cp.ground_objects:
|
||||
if not isinstance(ground_object, NavalGroundObject):
|
||||
continue
|
||||
|
||||
if ground_object.is_dead:
|
||||
continue
|
||||
|
||||
yield ground_object
|
||||
|
||||
def threatening_ships(self) -> Iterator[TheaterGroundObject]:
|
||||
"""Iterates over enemy ships near friendly control points.
|
||||
|
||||
Groups are sorted by their closest proximity to any friendly control
|
||||
point (airfield or fleet).
|
||||
"""
|
||||
return self._targets_by_range(self.enemy_ships())
|
||||
|
||||
def _targets_by_range(
|
||||
self,
|
||||
targets: Iterable[MissionTarget]) -> Iterator[TheaterGroundObject]:
|
||||
target_ranges: List[Tuple[MissionTarget, int]] = []
|
||||
for target in targets:
|
||||
ranges: List[int] = []
|
||||
for cp in self.friendly_control_points():
|
||||
ranges.append(group.distance_to(cp))
|
||||
groups.append((group, min(ranges)))
|
||||
ranges.append(target.distance_to(cp))
|
||||
target_ranges.append((target, min(ranges)))
|
||||
|
||||
groups = sorted(groups, key=operator.itemgetter(1))
|
||||
for group, _range in groups:
|
||||
yield group
|
||||
target_ranges = sorted(target_ranges, key=operator.itemgetter(1))
|
||||
for target, _range in target_ranges:
|
||||
yield target
|
||||
|
||||
def strike_targets(self) -> Iterator[TheaterGroundObject]:
|
||||
"""Iterates over enemy strike targets.
|
||||
@ -333,11 +356,17 @@ class ObjectiveFinder:
|
||||
point (airfield or fleet).
|
||||
"""
|
||||
targets: List[Tuple[TheaterGroundObject, int]] = []
|
||||
# Control points might have the same ground object several times, for
|
||||
# some reason.
|
||||
# Building objectives are made of several individual TGOs (one per
|
||||
# building).
|
||||
found_targets: Set[str] = set()
|
||||
for enemy_cp in self.enemy_control_points():
|
||||
for ground_object in enemy_cp.ground_objects:
|
||||
if isinstance(ground_object, VehicleGroupGroundObject):
|
||||
# BAI target, not strike target.
|
||||
continue
|
||||
if isinstance(ground_object, NavalGroundObject):
|
||||
# Anti-ship target, not strike target.
|
||||
continue
|
||||
if ground_object.is_dead:
|
||||
continue
|
||||
if ground_object.name in found_targets:
|
||||
@ -440,6 +469,7 @@ class CoalitionMissionPlanner:
|
||||
# TODO: Merge into doctrine, also limit by aircraft.
|
||||
MAX_CAP_RANGE = nm_to_meter(100)
|
||||
MAX_CAS_RANGE = nm_to_meter(50)
|
||||
MAX_ANTISHIP_RANGE = nm_to_meter(150)
|
||||
MAX_BAI_RANGE = nm_to_meter(150)
|
||||
MAX_SEAD_RANGE = nm_to_meter(150)
|
||||
MAX_STRIKE_RANGE = nm_to_meter(150)
|
||||
@ -476,6 +506,13 @@ class CoalitionMissionPlanner:
|
||||
ProposedFlight(FlightType.ESCORT, 2, self.MAX_SEAD_RANGE),
|
||||
])
|
||||
|
||||
for group in self.objective_finder.threatening_ships():
|
||||
yield ProposedMission(group, [
|
||||
ProposedFlight(FlightType.ANTISHIP, 2, self.MAX_ANTISHIP_RANGE),
|
||||
# TODO: Max escort range.
|
||||
ProposedFlight(FlightType.ESCORT, 2, self.MAX_ANTISHIP_RANGE),
|
||||
])
|
||||
|
||||
for group in self.objective_finder.threatening_vehicle_groups():
|
||||
yield ProposedMission(group, [
|
||||
ProposedFlight(FlightType.BAI, 2, self.MAX_BAI_RANGE),
|
||||
|
||||
@ -444,6 +444,7 @@ STRIKE_PREFERRED = [
|
||||
ANTISHIP_CAPABLE = [
|
||||
Su_24M,
|
||||
Su_17M4,
|
||||
FA_18C_hornet,
|
||||
F_A_18C,
|
||||
F_15E,
|
||||
AV8BNA,
|
||||
@ -458,7 +459,15 @@ ANTISHIP_CAPABLE = [
|
||||
Tornado_GR4,
|
||||
|
||||
Ju_88A4,
|
||||
Rafale_A_S
|
||||
Rafale_A_S,
|
||||
]
|
||||
|
||||
ANTISHIP_PREFERRED = [
|
||||
FA_18C_hornet,
|
||||
F_A_18C,
|
||||
JF_17,
|
||||
Rafale_A_S,
|
||||
Su_24M,
|
||||
]
|
||||
|
||||
DRONES = [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user