From 2ca875192af296a1a687ef309c6439e30e6841d4 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 7 May 2021 18:17:17 -0700 Subject: [PATCH] Save budget for filling whole packages. No sense filling airbases with cheap escorts if we'll never afford the rest of the package. Filling the airbases with cheap escorts also makes it impossible to buy the rest of the package when the faction eventually does have the money since there's nowhere to park the needed aircraft. https://github.com/dcs-liberation/dcs_liberation/issues/1058 --- changelog.md | 1 + game/procurement.py | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index 3b0feaa1..b743de27 100644 --- a/changelog.md +++ b/changelog.md @@ -16,6 +16,7 @@ Saves from 2.5 are not compatible with 3.0. * **[Campaign AI]** Fixed bug causing AI to over-purchase cheap aircraft. * **[Campaign AI]** Auto planner will no longer attempt to plan missions for which the faction has no compatible aircraft. +* **[Campaign AI]** Stop purchasing aircraft after the first unaffordable package to attempt to complete more packages rather than filling airfields with cheap escorts that will never be used. # 2.5.1 diff --git a/game/procurement.py b/game/procurement.py index d3410a12..c88b7218 100644 --- a/game/procurement.py +++ b/game/procurement.py @@ -3,7 +3,7 @@ from __future__ import annotations import math import random from dataclasses import dataclass -from typing import Iterator, List, Optional, TYPE_CHECKING, Type +from typing import Iterator, List, Optional, TYPE_CHECKING, Tuple, Type from dcs.unittype import FlyingType, VehicleType @@ -194,7 +194,7 @@ class ProcurementAi: def fulfill_aircraft_request( self, request: AircraftProcurementRequest, budget: float - ) -> float: + ) -> Tuple[float, bool]: for airbase in self.best_airbases_for(request): unit = self.affordable_aircraft_for(request, airbase, budget) if unit is None: @@ -207,12 +207,22 @@ class ProcurementAi: budget -= db.PRICES[unit] * request.number airbase.pending_unit_deliveries.order({unit: request.number}) - break - return budget + return budget, True + return budget, False def purchase_aircraft(self, budget: float) -> float: for request in self.game.procurement_requests_for(self.is_player): - budget = self.fulfill_aircraft_request(request, budget) + if not list(self.best_airbases_for(request)): + # No airbases in range of this request. Skip it. + continue + budget, fulfilled = self.fulfill_aircraft_request(request, budget) + if not fulfilled: + # The request was not fulfilled because we could not afford any suitable + # aircraft. Rather than continuing, which could proceed to buy tons of + # cheap escorts that will never allow us to plan a strike package, stop + # buying so we can save the budget until a turn where we *can* afford to + # fill the package. + break return budget @property