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 logging
|
||||||
import math
|
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.mapping import Point
|
||||||
from dcs.task import Task
|
from dcs.task import Task
|
||||||
@ -296,9 +296,6 @@ class Event:
|
|||||||
self.game.turn)
|
self.game.turn)
|
||||||
self.game.informations.append(info)
|
self.game.informations.append(info)
|
||||||
|
|
||||||
def skip(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def redeploy_units(self, cp):
|
def redeploy_units(self, cp):
|
||||||
""""
|
""""
|
||||||
Auto redeploy units to newly captured base
|
Auto redeploy units to newly captured base
|
||||||
@ -340,32 +337,25 @@ class Event:
|
|||||||
logging.info(info.text)
|
logging.info(info.text)
|
||||||
|
|
||||||
|
|
||||||
class UnitsDeliveryEvent(Event):
|
class UnitsDeliveryEvent:
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
def __init__(self, control_point: ControlPoint) -> None:
|
||||||
|
self.to_cp = control_point
|
||||||
self.units: Dict[Type[UnitType], int] = {}
|
self.units: Dict[Type[UnitType], int] = {}
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return "Pending delivery to {}".format(self.to_cp)
|
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():
|
for k, v in units.items():
|
||||||
self.units[k] = self.units.get(k, 0) + v
|
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:
|
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:
|
try:
|
||||||
price = PRICES[unit_type]
|
price = PRICES[unit_type]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -374,15 +364,14 @@ class UnitsDeliveryEvent(Event):
|
|||||||
|
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Refunding {count} {unit_type.id} at {self.to_cp.name}")
|
f"Refunding {count} {unit_type.id} at {self.to_cp.name}")
|
||||||
self.game.adjust_budget(price * count, player=self.to_cp.captured)
|
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}")
|
|
||||||
|
|
||||||
|
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.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
|
self.theater.controlpoints
|
||||||
)
|
)
|
||||||
|
|
||||||
for cp in self.theater.controlpoints:
|
|
||||||
cp.pending_unit_deliveries = self.units_delivery_event(cp)
|
|
||||||
|
|
||||||
self.sanitize_sides()
|
self.sanitize_sides()
|
||||||
|
|
||||||
self.on_load()
|
self.on_load()
|
||||||
@ -204,15 +201,6 @@ class Game:
|
|||||||
self.enemy_budget = 0
|
self.enemy_budget = 0
|
||||||
self.enemy_budget += Income(self, player=False).total
|
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:
|
def initiate_event(self, event: Event) -> UnitMap:
|
||||||
#assert event in self.events
|
#assert event in self.events
|
||||||
logging.info("Generating {} (regular)".format(event))
|
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.informations.append(Information("End of turn #" + str(self.turn), "-" * 40, 0))
|
||||||
self.turn += 1
|
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:
|
for control_point in self.theater.controlpoints:
|
||||||
control_point.process_turn()
|
control_point.process_turn(self)
|
||||||
|
|
||||||
self.process_enemy_income()
|
self.process_enemy_income()
|
||||||
|
|
||||||
@ -291,7 +271,6 @@ class Game:
|
|||||||
|
|
||||||
self.aircraft_inventory.reset()
|
self.aircraft_inventory.reset()
|
||||||
for cp in self.theater.controlpoints:
|
for cp in self.theater.controlpoints:
|
||||||
cp.pending_unit_deliveries = self.units_delivery_event(cp)
|
|
||||||
self.aircraft_inventory.set_from_control_point(cp)
|
self.aircraft_inventory.set_from_control_point(cp)
|
||||||
|
|
||||||
# Check for win or loss condition
|
# Check for win or loss condition
|
||||||
|
|||||||
@ -145,8 +145,7 @@ class ProcurementAi:
|
|||||||
break
|
break
|
||||||
|
|
||||||
budget -= db.PRICES[unit]
|
budget -= db.PRICES[unit]
|
||||||
assert cp.pending_unit_deliveries is not None
|
cp.pending_unit_deliveries.order({unit: 1})
|
||||||
cp.pending_unit_deliveries.deliver({unit: 1})
|
|
||||||
|
|
||||||
return budget
|
return budget
|
||||||
|
|
||||||
@ -190,8 +189,7 @@ class ProcurementAi:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
budget -= db.PRICES[unit] * request.number
|
budget -= db.PRICES[unit] * request.number
|
||||||
assert airbase.pending_unit_deliveries is not None
|
airbase.pending_unit_deliveries.order({unit: request.number})
|
||||||
airbase.pending_unit_deliveries.deliver({unit: request.number})
|
|
||||||
|
|
||||||
return budget
|
return budget
|
||||||
|
|
||||||
|
|||||||
@ -230,7 +230,7 @@ class ControlPoint(MissionTarget, ABC):
|
|||||||
self.cptype = cptype
|
self.cptype = cptype
|
||||||
# TODO: Should be Airbase specific.
|
# TODO: Should be Airbase specific.
|
||||||
self.stances: Dict[int, CombatStance] = {}
|
self.stances: Dict[int, CombatStance] = {}
|
||||||
self.pending_unit_deliveries: Optional[UnitsDeliveryEvent] = None
|
self.pending_unit_deliveries = UnitsDeliveryEvent(self)
|
||||||
|
|
||||||
self.target_position: Optional[Point] = None
|
self.target_position: Optional[Point] = None
|
||||||
|
|
||||||
@ -367,8 +367,7 @@ class ControlPoint(MissionTarget, ABC):
|
|||||||
|
|
||||||
# TODO: Should be Airbase specific.
|
# TODO: Should be Airbase specific.
|
||||||
def capture(self, game: Game, for_player: bool) -> None:
|
def capture(self, game: Game, for_player: bool) -> None:
|
||||||
if self.pending_unit_deliveries is not None:
|
self.pending_unit_deliveries.refund_all(game)
|
||||||
self.pending_unit_deliveries.refund_all()
|
|
||||||
|
|
||||||
if for_player:
|
if for_player:
|
||||||
self.captured = True
|
self.captured = True
|
||||||
@ -406,7 +405,6 @@ class ControlPoint(MissionTarget, ABC):
|
|||||||
return total
|
return total
|
||||||
|
|
||||||
def expected_aircraft_next_turn(self, game: Game) -> PendingOccupancy:
|
def expected_aircraft_next_turn(self, game: Game) -> PendingOccupancy:
|
||||||
assert self.pending_unit_deliveries
|
|
||||||
on_order = 0
|
on_order = 0
|
||||||
for unit_bought in self.pending_unit_deliveries.units:
|
for unit_bought in self.pending_unit_deliveries.units:
|
||||||
if issubclass(unit_bought, FlyingType):
|
if issubclass(unit_bought, FlyingType):
|
||||||
@ -443,7 +441,9 @@ class ControlPoint(MissionTarget, ABC):
|
|||||||
return
|
return
|
||||||
self.runway_status.begin_repair()
|
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
|
runway_status = self.runway_status
|
||||||
if runway_status is not None:
|
if runway_status is not None:
|
||||||
runway_status.process_turn()
|
runway_status.process_turn()
|
||||||
|
|||||||
@ -36,7 +36,6 @@ class QRecruitBehaviour:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def pending_deliveries(self) -> UnitsDeliveryEvent:
|
def pending_deliveries(self) -> UnitsDeliveryEvent:
|
||||||
assert self.cp.pending_unit_deliveries
|
|
||||||
return self.cp.pending_unit_deliveries
|
return self.cp.pending_unit_deliveries
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -128,7 +127,7 @@ class QRecruitBehaviour:
|
|||||||
def buy(self, unit_type: Type[UnitType]):
|
def buy(self, unit_type: Type[UnitType]):
|
||||||
price = db.PRICES[unit_type]
|
price = db.PRICES[unit_type]
|
||||||
if self.budget >= price:
|
if self.budget >= price:
|
||||||
self.pending_deliveries.deliver({unit_type: 1})
|
self.pending_deliveries.order({unit_type: 1})
|
||||||
self.budget -= price
|
self.budget -= price
|
||||||
else:
|
else:
|
||||||
# TODO : display modal warning
|
# TODO : display modal warning
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user