mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Move calculation of aircraft amounts into game.
The planner needs to know how much space is still expected to be available next turn.
This commit is contained in:
parent
f8b2dbe283
commit
c4b8a41742
@ -352,11 +352,13 @@ 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):
|
||||
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,
|
||||
@ -364,17 +366,16 @@ class UnitsDeliveryEvent(Event):
|
||||
attacker_name=attacker_name,
|
||||
defender_name=defender_name)
|
||||
|
||||
self.units: Dict[UnitType, int] = {}
|
||||
self.units: Dict[Type[UnitType], int] = {}
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return "Pending delivery to {}".format(self.to_cp)
|
||||
|
||||
def deliver(self, units: Dict[UnitType, int]):
|
||||
def deliver(self, units: Dict[Type[UnitType], int]) -> None:
|
||||
for k, v in units.items():
|
||||
self.units[k] = self.units.get(k, 0) + v
|
||||
|
||||
def skip(self):
|
||||
|
||||
def skip(self) -> None:
|
||||
for k, v in self.units.items():
|
||||
info = Information("Ally Reinforcement", str(k.id) + " x " + str(v) + " at " + self.to_cp.name, self.game.turn)
|
||||
self.game.informations.append(info)
|
||||
|
||||
@ -316,7 +316,7 @@ class Game:
|
||||
if i > 50 or budget_for_aircraft <= 0:
|
||||
break
|
||||
target_cp = random.choice(potential_cp_armor)
|
||||
if target_cp.base.total_planes >= MAX_AIRCRAFT:
|
||||
if target_cp.base.total_aircraft >= MAX_AIRCRAFT:
|
||||
continue
|
||||
unit = random.choice(potential_units)
|
||||
price = db.PRICES[unit] * 2
|
||||
|
||||
@ -4,9 +4,8 @@ import math
|
||||
import typing
|
||||
from typing import Dict, Type
|
||||
|
||||
from dcs.planes import PlaneType
|
||||
from dcs.task import CAP, CAS, Embarking, PinpointStrike, Task
|
||||
from dcs.unittype import UnitType, VehicleType
|
||||
from dcs.unittype import FlyingType, UnitType, VehicleType
|
||||
from dcs.vehicles import AirDefence, Armor
|
||||
|
||||
from game import db
|
||||
@ -21,20 +20,16 @@ BASE_MIN_STRENGTH = 0
|
||||
|
||||
|
||||
class Base:
|
||||
aircraft = {} # type: typing.Dict[PlaneType, int]
|
||||
armor = {} # type: typing.Dict[VehicleType, int]
|
||||
aa = {} # type: typing.Dict[AirDefence, int]
|
||||
strength = 1 # type: float
|
||||
|
||||
def __init__(self):
|
||||
self.aircraft = {}
|
||||
self.armor = {}
|
||||
self.aa = {}
|
||||
self.aircraft: Dict[FlyingType, int] = {}
|
||||
self.armor: Dict[VehicleType, int] = {}
|
||||
self.aa: Dict[AirDefence, int] = {}
|
||||
self.commision_points: Dict[Type, float] = {}
|
||||
self.strength = 1
|
||||
|
||||
@property
|
||||
def total_planes(self) -> int:
|
||||
def total_aircraft(self) -> int:
|
||||
return sum(self.aircraft.values())
|
||||
|
||||
@property
|
||||
@ -83,7 +78,7 @@ class Base:
|
||||
logging.info("{} for {} ({}): {}".format(self, for_type, count, result))
|
||||
return result
|
||||
|
||||
def _find_best_planes(self, for_type: Task, count: int) -> typing.Dict[PlaneType, int]:
|
||||
def _find_best_planes(self, for_type: Task, count: int) -> typing.Dict[FlyingType, int]:
|
||||
return self._find_best_unit(self.aircraft, for_type, count)
|
||||
|
||||
def _find_best_armor(self, for_type: Task, count: int) -> typing.Dict[Armor, int]:
|
||||
@ -155,7 +150,7 @@ class Base:
|
||||
if task:
|
||||
count = sum([v for k, v in self.aircraft.items() if db.unit_task(k) == task])
|
||||
else:
|
||||
count = self.total_planes
|
||||
count = self.total_aircraft
|
||||
|
||||
count = int(math.ceil(count * PLANES_SCRAMBLE_FACTOR * self.strength))
|
||||
return min(min(max(count, PLANES_SCRAMBLE_MIN_BASE), int(PLANES_SCRAMBLE_MAX_BASE * multiplier)), count)
|
||||
@ -167,18 +162,18 @@ class Base:
|
||||
# previous logic removed because we always want the full air defense capabilities.
|
||||
return self.total_aa
|
||||
|
||||
def scramble_sweep(self, multiplier: float) -> typing.Dict[PlaneType, int]:
|
||||
def scramble_sweep(self, multiplier: float) -> typing.Dict[FlyingType, int]:
|
||||
return self._find_best_planes(CAP, self.scramble_count(multiplier, CAP))
|
||||
|
||||
def scramble_last_defense(self):
|
||||
# return as many CAP-capable aircraft as we can since this is the last defense of the base
|
||||
# (but not more than 20 - that's just nuts)
|
||||
return self._find_best_planes(CAP, min(self.total_planes, 20))
|
||||
return self._find_best_planes(CAP, min(self.total_aircraft, 20))
|
||||
|
||||
def scramble_cas(self, multiplier: float) -> typing.Dict[PlaneType, int]:
|
||||
def scramble_cas(self, multiplier: float) -> typing.Dict[FlyingType, int]:
|
||||
return self._find_best_planes(CAS, self.scramble_count(multiplier, CAS))
|
||||
|
||||
def scramble_interceptors(self, multiplier: float) -> typing.Dict[PlaneType, int]:
|
||||
def scramble_interceptors(self, multiplier: float) -> typing.Dict[FlyingType, int]:
|
||||
return self._find_best_planes(CAP, self.scramble_count(multiplier, CAP))
|
||||
|
||||
def assemble_attack(self) -> typing.Dict[Armor, int]:
|
||||
|
||||
@ -376,6 +376,15 @@ class ControlPoint(MissionTarget):
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def expected_aircraft_next_turn(self) -> int:
|
||||
total = self.base.total_aircraft
|
||||
assert self.pending_unit_deliveries
|
||||
for unit_bought in self.pending_unit_deliveries.units:
|
||||
if issubclass(unit_bought, FlyingType):
|
||||
total += self.pending_unit_deliveries.units[unit_bought]
|
||||
return total
|
||||
|
||||
|
||||
class OffMapSpawn(ControlPoint):
|
||||
def __init__(self, id: int, name: str, position: Point):
|
||||
|
||||
@ -57,7 +57,7 @@ class QBaseMenu2(QDialog):
|
||||
title = QLabel("<b>" + self.cp.name + "</b>")
|
||||
title.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||||
title.setProperty("style", "base-title")
|
||||
unitsPower = QLabel("{} / {} / Runway : {}".format(self.cp.base.total_planes, self.cp.base.total_armor,
|
||||
unitsPower = QLabel("{} / {} / Runway : {}".format(self.cp.base.total_aircraft, self.cp.base.total_armor,
|
||||
"Available" if self.cp.has_runway() else "Unavailable"))
|
||||
self.topLayout.addWidget(title)
|
||||
self.topLayout.addWidget(unitsPower)
|
||||
|
||||
@ -126,13 +126,6 @@ class QRecruitBehaviour:
|
||||
QRecruitBehaviour.BUDGET_FORMAT.format(self.budget))
|
||||
|
||||
def buy(self, unit_type):
|
||||
|
||||
if self.maximum_units > 0:
|
||||
if self.total_units + 1 > self.maximum_units:
|
||||
logging.info("Not enough space left !")
|
||||
# TODO : display modal warning
|
||||
return
|
||||
|
||||
price = db.PRICES[unit_type]
|
||||
if self.budget >= price:
|
||||
self.pending_deliveries.deliver({unit_type: 1})
|
||||
@ -158,19 +151,6 @@ class QRecruitBehaviour:
|
||||
self._update_count_label(unit_type)
|
||||
self.update_available_budget()
|
||||
|
||||
@property
|
||||
def total_units(self):
|
||||
total = 0
|
||||
for unit_type in self.recruitables_types:
|
||||
total += self.cp.base.total_units(unit_type)
|
||||
|
||||
if self.pending_deliveries:
|
||||
for unit_bought in self.pending_deliveries.units:
|
||||
if db.unit_task(unit_bought) in self.recruitables_types:
|
||||
total += self.pending_deliveries.units[unit_bought]
|
||||
|
||||
return total
|
||||
|
||||
def set_maximum_units(self, maximum_units):
|
||||
"""
|
||||
Set the maximum number of units that can be bought
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import logging
|
||||
from typing import Optional, Set
|
||||
|
||||
from PySide2.QtCore import Qt
|
||||
@ -37,7 +38,7 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
|
||||
self.bought_amount_labels = {}
|
||||
self.existing_units_labels = {}
|
||||
|
||||
self.hangar_status = QHangarStatus(self.total_units, self.cp.available_aircraft_slots)
|
||||
self.hangar_status = QHangarStatus(self.total_aircraft, self.cp.available_aircraft_slots)
|
||||
|
||||
self.init_ui()
|
||||
|
||||
@ -80,8 +81,18 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def buy(self, unit_type):
|
||||
if self.maximum_units > 0:
|
||||
if self.total_aircraft + 1 > self.maximum_units:
|
||||
logging.debug(f"No space for additional aircraft at {self.cp}.")
|
||||
return
|
||||
|
||||
super().buy(unit_type)
|
||||
self.hangar_status.update_label(self.total_units, self.cp.available_aircraft_slots)
|
||||
self.hangar_status.update_label(self.total_aircraft,
|
||||
self.cp.available_aircraft_slots)
|
||||
|
||||
@property
|
||||
def total_aircraft(self) -> int:
|
||||
return self.cp.expected_aircraft_next_turn
|
||||
|
||||
def sell(self, unit_type: UnitType):
|
||||
# Don't need to remove aircraft from the inventory if we're canceling
|
||||
@ -99,7 +110,7 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
|
||||
"assigned to a mission?", QMessageBox.Ok)
|
||||
return
|
||||
super().sell(unit_type)
|
||||
self.hangar_status.update_label(self.total_units, self.cp.available_aircraft_slots)
|
||||
self.hangar_status.update_label(self.total_aircraft, self.cp.available_aircraft_slots)
|
||||
|
||||
|
||||
class QHangarStatus(QHBoxLayout):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user