Move transfers one CP per turn.

https://github.com/Khopa/dcs_liberation/issues/824
This commit is contained in:
Dan Albert
2021-04-17 19:03:33 -07:00
parent 65f6a4eddd
commit bd9cbf5e3b
5 changed files with 154 additions and 21 deletions

View File

@@ -1,9 +1,10 @@
import logging
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import Dict, List, Type
from dcs.unittype import VehicleType
from game.theater import ControlPoint
from game.theater.supplyroutes import SupplyRoute
@dataclass
@@ -30,6 +31,19 @@ class RoadTransferOrder(TransferOrder):
#: The units being transferred.
units: Dict[Type[VehicleType], int]
#: The current position of the group being transferred. Groups move one control
#: point a turn through the supply line.
position: ControlPoint = field(init=False)
def __post_init__(self) -> None:
self.position = self.origin
def path(self) -> List[ControlPoint]:
supply_route = SupplyRoute.for_control_point(self.position)
if supply_route is None:
raise RuntimeError(f"Supply route from {self.position.name} interrupted")
return supply_route.shortest_path_between(self.position, self.destination)
class PendingTransfers:
def __init__(self) -> None:
@@ -50,27 +64,66 @@ class PendingTransfers:
self.pending_transfers.remove(transfer)
transfer.origin.base.commision_units(transfer.units)
def complete_transfers(self) -> None:
def perform_transfers(self) -> None:
incomplete = []
for transfer in self.pending_transfers:
self.complete_transfer(transfer)
self.pending_transfers.clear()
if not self.perform_transfer(transfer):
incomplete.append(transfer)
self.pending_transfers = incomplete
@staticmethod
def complete_transfer(transfer: RoadTransferOrder) -> None:
if transfer.player == transfer.destination.captured:
def perform_transfer(self, transfer: RoadTransferOrder) -> bool:
if transfer.player != transfer.destination.captured:
logging.info(
f"Transfer destination {transfer.destination.name} was captured."
)
self.handle_route_interrupted(transfer)
return True
supply_route = SupplyRoute.for_control_point(transfer.destination)
if supply_route is None or transfer.position not in supply_route:
logging.info(
f"Route from {transfer.position.name} to {transfer.destination.name} "
"was cut off."
)
self.handle_route_interrupted(transfer)
return True
path = transfer.path()
next_hop = path[0]
if next_hop == transfer.destination:
logging.info(
f"Units transferred from {transfer.origin.name} to "
f"{transfer.destination.name}"
)
transfer.destination.base.commision_units(transfer.units)
elif transfer.player == transfer.origin.captured:
logging.info(
f"{transfer.destination.name} was captured. Transferring units are "
f"returning to {transfer.origin.name}"
)
transfer.origin.base.commision_units(transfer.units)
else:
logging.info(
f"Both {transfer.origin.name} and {transfer.destination.name} were "
"captured. Units were surrounded and captured during transfer."
)
return True
logging.info(
f"Units transferring from {transfer.origin.name} to "
f"{transfer.destination.name} arrived at {next_hop.name}. {len(path) - 1} "
"turns remaining."
)
transfer.position = next_hop
return False
@staticmethod
def handle_route_interrupted(transfer: RoadTransferOrder):
# Halt the transfer in place if safe.
if transfer.player == transfer.position.captured:
logging.info(f"Transferring units are halting at {transfer.position.name}.")
transfer.position.base.commision_units(transfer.units)
return
# If the current position was captured attempt to divert to a neighboring
# friendly CP.
for connected in transfer.position.connected_points:
if connected.captured == transfer.player:
logging.info(f"Transferring units are re-routing to {connected.name}.")
connected.base.commision_units(transfer.units)
return
# If the units are cutoff they are destroyed.
logging.info(
f"Both {transfer.position.name} and {transfer.destination.name} were "
"captured. Units were surrounded and destroyed during transfer."
)