mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Decouple unit deliveries and conflict events.
Fixes https://github.com/Khopa/dcs_liberation/issues/692 and lets us clean up the interface quite a bit.
This commit is contained in:
parent
de325c1208
commit
9671542bdf
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import math
|
||||
from typing import Dict, List, TYPE_CHECKING, Type
|
||||
from typing import Dict, Iterator, List, TYPE_CHECKING, Tuple, Type
|
||||
|
||||
from dcs.mapping import Point
|
||||
from dcs.task import Task
|
||||
@ -296,9 +296,6 @@ class Event:
|
||||
self.game.turn)
|
||||
self.game.informations.append(info)
|
||||
|
||||
def skip(self):
|
||||
pass
|
||||
|
||||
def redeploy_units(self, cp):
|
||||
""""
|
||||
Auto redeploy units to newly captured base
|
||||
@ -340,32 +337,25 @@ class Event:
|
||||
logging.info(info.text)
|
||||
|
||||
|
||||
class UnitsDeliveryEvent(Event):
|
||||
|
||||
informational = True
|
||||
|
||||
def __init__(self, attacker_name: str, defender_name: str,
|
||||
from_cp: ControlPoint, to_cp: ControlPoint,
|
||||
game: Game) -> None:
|
||||
super(UnitsDeliveryEvent, self).__init__(game=game,
|
||||
location=to_cp.position,
|
||||
from_cp=from_cp,
|
||||
target_cp=to_cp,
|
||||
attacker_name=attacker_name,
|
||||
defender_name=defender_name)
|
||||
class UnitsDeliveryEvent:
|
||||
|
||||
def __init__(self, control_point: ControlPoint) -> None:
|
||||
self.to_cp = control_point
|
||||
self.units: Dict[Type[UnitType], int] = {}
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "Pending delivery to {}".format(self.to_cp)
|
||||
|
||||
def deliver(self, units: Dict[Type[UnitType], int]) -> None:
|
||||
def order(self, units: Dict[Type[UnitType], int]) -> None:
|
||||
for k, v in units.items():
|
||||
self.units[k] = self.units.get(k, 0) + v
|
||||
|
||||
def refund_all(self) -> None:
|
||||
def consume_each_order(self) -> Iterator[Tuple[Type[UnitType], int]]:
|
||||
while self.units:
|
||||
unit_type, count = self.units.popitem()
|
||||
yield self.units.popitem()
|
||||
|
||||
def refund_all(self, game: Game) -> None:
|
||||
for unit_type, count in self.consume_each_order():
|
||||
try:
|
||||
price = PRICES[unit_type]
|
||||
except KeyError:
|
||||
@ -374,15 +364,14 @@ class UnitsDeliveryEvent(Event):
|
||||
|
||||
logging.info(
|
||||
f"Refunding {count} {unit_type.id} at {self.to_cp.name}")
|
||||
self.game.adjust_budget(price * count, player=self.to_cp.captured)
|
||||
|
||||
def skip(self) -> None:
|
||||
for k, v in self.units.items():
|
||||
if self.to_cp.captured:
|
||||
name = "Ally "
|
||||
else:
|
||||
name = "Enemy "
|
||||
self.game.message(
|
||||
f"{name} reinforcements: {k.id} x {v} at {self.to_cp.name}")
|
||||
game.adjust_budget(price * count, player=self.to_cp.captured)
|
||||
|
||||
def process(self, game: Game) -> None:
|
||||
for unit_type, count in self.units.items():
|
||||
coalition = "Ally" if self.to_cp.captured else "Enemy"
|
||||
aircraft = unit_type.id
|
||||
name = self.to_cp.name
|
||||
game.message(
|
||||
f"{coalition} reinforcements: {aircraft} x {count} at {name}")
|
||||
self.to_cp.base.commision_units(self.units)
|
||||
self.units = {}
|
||||
|
||||
23
game/game.py
23
game/game.py
@ -110,9 +110,6 @@ class Game:
|
||||
self.theater.controlpoints
|
||||
)
|
||||
|
||||
for cp in self.theater.controlpoints:
|
||||
cp.pending_unit_deliveries = self.units_delivery_event(cp)
|
||||
|
||||
self.sanitize_sides()
|
||||
|
||||
self.on_load()
|
||||
@ -204,15 +201,6 @@ class Game:
|
||||
self.enemy_budget = 0
|
||||
self.enemy_budget += Income(self, player=False).total
|
||||
|
||||
def units_delivery_event(self, to_cp: ControlPoint) -> UnitsDeliveryEvent:
|
||||
event = UnitsDeliveryEvent(attacker_name=self.player_name,
|
||||
defender_name=self.player_name,
|
||||
from_cp=to_cp,
|
||||
to_cp=to_cp,
|
||||
game=self)
|
||||
self.events.append(event)
|
||||
return event
|
||||
|
||||
def initiate_event(self, event: Event) -> UnitMap:
|
||||
#assert event in self.events
|
||||
logging.info("Generating {} (regular)".format(event))
|
||||
@ -244,16 +232,8 @@ class Game:
|
||||
self.informations.append(Information("End of turn #" + str(self.turn), "-" * 40, 0))
|
||||
self.turn += 1
|
||||
|
||||
for event in self.events:
|
||||
if self.settings.version == "dev":
|
||||
# don't damage player CPs in by skipping in dev mode
|
||||
if isinstance(event, UnitsDeliveryEvent):
|
||||
event.skip()
|
||||
else:
|
||||
event.skip()
|
||||
|
||||
for control_point in self.theater.controlpoints:
|
||||
control_point.process_turn()
|
||||
control_point.process_turn(self)
|
||||
|
||||
self.process_enemy_income()
|
||||
|
||||
@ -291,7 +271,6 @@ class Game:
|
||||
|
||||
self.aircraft_inventory.reset()
|
||||
for cp in self.theater.controlpoints:
|
||||
cp.pending_unit_deliveries = self.units_delivery_event(cp)
|
||||
self.aircraft_inventory.set_from_control_point(cp)
|
||||
|
||||
# Check for win or loss condition
|
||||
|
||||
@ -145,8 +145,7 @@ class ProcurementAi:
|
||||
break
|
||||
|
||||
budget -= db.PRICES[unit]
|
||||
assert cp.pending_unit_deliveries is not None
|
||||
cp.pending_unit_deliveries.deliver({unit: 1})
|
||||
cp.pending_unit_deliveries.order({unit: 1})
|
||||
|
||||
return budget
|
||||
|
||||
@ -190,8 +189,7 @@ class ProcurementAi:
|
||||
continue
|
||||
|
||||
budget -= db.PRICES[unit] * request.number
|
||||
assert airbase.pending_unit_deliveries is not None
|
||||
airbase.pending_unit_deliveries.deliver({unit: request.number})
|
||||
airbase.pending_unit_deliveries.order({unit: request.number})
|
||||
|
||||
return budget
|
||||
|
||||
|
||||
@ -230,7 +230,7 @@ class ControlPoint(MissionTarget, ABC):
|
||||
self.cptype = cptype
|
||||
# TODO: Should be Airbase specific.
|
||||
self.stances: Dict[int, CombatStance] = {}
|
||||
self.pending_unit_deliveries: Optional[UnitsDeliveryEvent] = None
|
||||
self.pending_unit_deliveries = UnitsDeliveryEvent(self)
|
||||
|
||||
self.target_position: Optional[Point] = None
|
||||
|
||||
@ -367,8 +367,7 @@ class ControlPoint(MissionTarget, ABC):
|
||||
|
||||
# TODO: Should be Airbase specific.
|
||||
def capture(self, game: Game, for_player: bool) -> None:
|
||||
if self.pending_unit_deliveries is not None:
|
||||
self.pending_unit_deliveries.refund_all()
|
||||
self.pending_unit_deliveries.refund_all(game)
|
||||
|
||||
if for_player:
|
||||
self.captured = True
|
||||
@ -406,7 +405,6 @@ class ControlPoint(MissionTarget, ABC):
|
||||
return total
|
||||
|
||||
def expected_aircraft_next_turn(self, game: Game) -> PendingOccupancy:
|
||||
assert self.pending_unit_deliveries
|
||||
on_order = 0
|
||||
for unit_bought in self.pending_unit_deliveries.units:
|
||||
if issubclass(unit_bought, FlyingType):
|
||||
@ -443,7 +441,9 @@ class ControlPoint(MissionTarget, ABC):
|
||||
return
|
||||
self.runway_status.begin_repair()
|
||||
|
||||
def process_turn(self) -> None:
|
||||
def process_turn(self, game: Game) -> None:
|
||||
self.pending_unit_deliveries.process(game)
|
||||
|
||||
runway_status = self.runway_status
|
||||
if runway_status is not None:
|
||||
runway_status.process_turn()
|
||||
|
||||
@ -36,7 +36,6 @@ class QRecruitBehaviour:
|
||||
|
||||
@property
|
||||
def pending_deliveries(self) -> UnitsDeliveryEvent:
|
||||
assert self.cp.pending_unit_deliveries
|
||||
return self.cp.pending_unit_deliveries
|
||||
|
||||
@property
|
||||
@ -128,7 +127,7 @@ class QRecruitBehaviour:
|
||||
def buy(self, unit_type: Type[UnitType]):
|
||||
price = db.PRICES[unit_type]
|
||||
if self.budget >= price:
|
||||
self.pending_deliveries.deliver({unit_type: 1})
|
||||
self.pending_deliveries.order({unit_type: 1})
|
||||
self.budget -= price
|
||||
else:
|
||||
# TODO : display modal warning
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user