mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Migrate IP placement to WaypointSolver.
This commit is contained in:
173
game/flightplan/ipsolver.py
Normal file
173
game/flightplan/ipsolver.py
Normal file
@@ -0,0 +1,173 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from typing import Any
|
||||
|
||||
from shapely.geometry import MultiPolygon, Point
|
||||
from shapely.geometry.base import BaseGeometry
|
||||
|
||||
from game.data.doctrine import Doctrine
|
||||
from game.flightplan.waypointsolver import WaypointSolver
|
||||
from game.flightplan.waypointstrategy import WaypointStrategy
|
||||
from game.utils import meters, nautical_miles
|
||||
|
||||
MIN_DISTANCE_FROM_DEPARTURE = nautical_miles(5)
|
||||
|
||||
|
||||
class ThreatTolerantIpStrategy(WaypointStrategy):
|
||||
def __init__(
|
||||
self,
|
||||
departure: Point,
|
||||
target: Point,
|
||||
doctrine: Doctrine,
|
||||
threat_zones: MultiPolygon,
|
||||
) -> None:
|
||||
super().__init__(threat_zones)
|
||||
self.prerequisite(target).min_distance_from(
|
||||
departure, doctrine.min_ingress_distance
|
||||
)
|
||||
self.require().at_least(MIN_DISTANCE_FROM_DEPARTURE).away_from(departure)
|
||||
self.require().at_most(meters(departure.distance(target))).away_from(departure)
|
||||
self.require().at_least(doctrine.min_ingress_distance).away_from(target)
|
||||
max_ip_range = min(
|
||||
doctrine.max_ingress_distance, meters(departure.distance(target))
|
||||
)
|
||||
self.require().at_most(max_ip_range).away_from(target)
|
||||
self.threat_tolerance(target, max_ip_range, nautical_miles(5))
|
||||
self.nearest(departure)
|
||||
|
||||
|
||||
class UnsafeIpStrategy(WaypointStrategy):
|
||||
def __init__(
|
||||
self,
|
||||
departure: Point,
|
||||
target: Point,
|
||||
doctrine: Doctrine,
|
||||
threat_zones: MultiPolygon,
|
||||
) -> None:
|
||||
super().__init__(threat_zones)
|
||||
self.prerequisite(target).min_distance_from(
|
||||
departure, doctrine.min_ingress_distance
|
||||
)
|
||||
self.require().at_least(MIN_DISTANCE_FROM_DEPARTURE).away_from(
|
||||
departure, "departure"
|
||||
)
|
||||
self.require().at_most(meters(departure.distance(target))).away_from(
|
||||
departure, "departure"
|
||||
)
|
||||
self.require().at_least(doctrine.min_ingress_distance).away_from(
|
||||
target, "target"
|
||||
)
|
||||
max_ip_range = min(
|
||||
doctrine.max_ingress_distance, meters(departure.distance(target))
|
||||
)
|
||||
self.require().at_most(max_ip_range).away_from(target, "target")
|
||||
self.nearest(departure)
|
||||
|
||||
|
||||
class SafeIpStrategy(WaypointStrategy):
|
||||
def __init__(
|
||||
self,
|
||||
departure: Point,
|
||||
target: Point,
|
||||
doctrine: Doctrine,
|
||||
threat_zones: MultiPolygon,
|
||||
) -> None:
|
||||
super().__init__(threat_zones)
|
||||
self.prerequisite(departure).is_safe()
|
||||
self.prerequisite(target).min_distance_from(
|
||||
departure, doctrine.min_ingress_distance
|
||||
)
|
||||
self.require().at_least(MIN_DISTANCE_FROM_DEPARTURE).away_from(
|
||||
departure, "departure"
|
||||
)
|
||||
self.require().at_most(meters(departure.distance(target))).away_from(
|
||||
departure, "departure"
|
||||
)
|
||||
self.require().at_least(doctrine.min_ingress_distance).away_from(
|
||||
target, "target"
|
||||
)
|
||||
self.require().at_most(
|
||||
min(doctrine.max_ingress_distance, meters(departure.distance(target)))
|
||||
).away_from(target, "target")
|
||||
self.require().safe()
|
||||
self.nearest(departure)
|
||||
|
||||
|
||||
class SafeBackTrackingIpStrategy(WaypointStrategy):
|
||||
def __init__(
|
||||
self,
|
||||
departure: Point,
|
||||
target: Point,
|
||||
doctrine: Doctrine,
|
||||
threat_zones: MultiPolygon,
|
||||
) -> None:
|
||||
super().__init__(threat_zones)
|
||||
self.require().at_least(MIN_DISTANCE_FROM_DEPARTURE).away_from(
|
||||
departure, "departure"
|
||||
)
|
||||
self.require().at_least(doctrine.min_ingress_distance).away_from(
|
||||
target, "target"
|
||||
)
|
||||
self.require().at_most(doctrine.max_ingress_distance).away_from(
|
||||
target, "target"
|
||||
)
|
||||
self.require().safe()
|
||||
self.nearest(departure)
|
||||
|
||||
|
||||
class UnsafeBackTrackingIpStrategy(WaypointStrategy):
|
||||
def __init__(
|
||||
self,
|
||||
departure: Point,
|
||||
target: Point,
|
||||
doctrine: Doctrine,
|
||||
threat_zones: MultiPolygon,
|
||||
) -> None:
|
||||
super().__init__(threat_zones)
|
||||
self.require().at_least(MIN_DISTANCE_FROM_DEPARTURE).away_from(
|
||||
departure, "departure"
|
||||
)
|
||||
self.require().at_least(doctrine.min_ingress_distance).away_from(
|
||||
target, "target"
|
||||
)
|
||||
self.require().at_most(doctrine.max_ingress_distance).away_from(
|
||||
target, "target"
|
||||
)
|
||||
self.nearest(departure)
|
||||
|
||||
|
||||
class IpSolver(WaypointSolver):
|
||||
def __init__(
|
||||
self,
|
||||
departure: Point,
|
||||
target: Point,
|
||||
doctrine: Doctrine,
|
||||
threat_zones: MultiPolygon,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.departure = departure
|
||||
self.target = target
|
||||
self.doctrine = doctrine
|
||||
self.threat_zones = threat_zones
|
||||
|
||||
self.add_strategy(SafeIpStrategy(departure, target, doctrine, threat_zones))
|
||||
self.add_strategy(
|
||||
ThreatTolerantIpStrategy(departure, target, doctrine, threat_zones)
|
||||
)
|
||||
self.add_strategy(UnsafeIpStrategy(departure, target, doctrine, threat_zones))
|
||||
self.add_strategy(
|
||||
SafeBackTrackingIpStrategy(departure, target, doctrine, threat_zones)
|
||||
)
|
||||
# TODO: The cases that require this are not covered by any tests.
|
||||
self.add_strategy(
|
||||
UnsafeBackTrackingIpStrategy(departure, target, doctrine, threat_zones)
|
||||
)
|
||||
|
||||
def describe_metadata(self) -> dict[str, Any]:
|
||||
return {"doctrine": self.doctrine.name}
|
||||
|
||||
def describe_inputs(self) -> Iterator[tuple[str, BaseGeometry]]:
|
||||
yield "departure", self.departure
|
||||
yield "target", self.target
|
||||
yield "threat_zones", self.threat_zones
|
||||
Reference in New Issue
Block a user