mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Aims to solve the issue where AirAssault won't plan against CPs that don't have an active frontline, including isolated CPs.
52 lines
2.2 KiB
Python
52 lines
2.2 KiB
Python
from collections.abc import Iterator
|
|
from dataclasses import dataclass
|
|
|
|
from game.commander.tasks.compound.destroyenemygroundunits import (
|
|
DestroyEnemyGroundUnits,
|
|
)
|
|
from game.commander.tasks.compound.reduceenemyfrontlinecapacity import (
|
|
ReduceEnemyFrontLineCapacity,
|
|
)
|
|
from game.commander.tasks.primitive.breakthroughattack import BreakthroughAttack
|
|
from game.commander.theaterstate import TheaterState
|
|
from game.htn import CompoundTask, Method
|
|
from game.theater import ControlPoint, FrontLine
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class CaptureBase(CompoundTask[TheaterState]):
|
|
front_line: FrontLine
|
|
|
|
def each_valid_method(self, state: TheaterState) -> Iterator[Method[TheaterState]]:
|
|
yield [BreakthroughAttack(self.front_line, state.context.coalition.player)]
|
|
yield [DestroyEnemyGroundUnits(self.front_line)]
|
|
if self.worth_destroying_ammo_depots(state):
|
|
yield [ReduceEnemyFrontLineCapacity(self.enemy_cp(state))]
|
|
|
|
def enemy_cp(self, state: TheaterState) -> ControlPoint:
|
|
return self.front_line.control_point_hostile_to(state.context.coalition.player)
|
|
|
|
def units_deployable(self, state: TheaterState, player: bool) -> int:
|
|
cp = self.front_line.control_point_friendly_to(player)
|
|
ammo_depots = list(state.ammo_dumps_at(cp))
|
|
return cp.deployable_front_line_units_with(len(ammo_depots))
|
|
|
|
def unit_cap(self, state: TheaterState, player: bool) -> int:
|
|
cp = self.front_line.control_point_friendly_to(player)
|
|
ammo_depots = list(state.ammo_dumps_at(cp))
|
|
return cp.front_line_capacity_with(len(ammo_depots))
|
|
|
|
def enemy_has_ammo_dumps(self, state: TheaterState) -> bool:
|
|
return bool(state.ammo_dumps_at(self.enemy_cp(state)))
|
|
|
|
def worth_destroying_ammo_depots(self, state: TheaterState) -> bool:
|
|
if not self.enemy_has_ammo_dumps(state):
|
|
return False
|
|
|
|
friendly_cap = self.unit_cap(state, state.context.coalition.player)
|
|
enemy_deployable = self.units_deployable(state, state.context.coalition.player)
|
|
|
|
# If the enemy can currently deploy 50% more units than we possibly could, it's
|
|
# worth killing an ammo depot.
|
|
return enemy_deployable / friendly_cap > 1.5
|