Account for time elapsed when leaving combat.

This commit is contained in:
Dan Albert 2022-03-07 23:23:52 -08:00
parent e36c62b30e
commit f63a107c11
8 changed files with 57 additions and 16 deletions

View File

@ -19,6 +19,7 @@ class FlightState(ABC):
def __init__(self, flight: Flight, settings: Settings) -> None:
self.flight = flight
self.settings = settings
self.avoid_further_combat = False
@property
def alive(self) -> bool:

View File

@ -24,9 +24,16 @@ class InCombat(InFlight):
self.previous_state = previous_state
self.combat = combat
def exit_combat(self) -> None:
# TODO: Account for time passed while frozen.
def exit_combat(
self,
events: GameUpdateEvents,
time: datetime,
elapsed_time: timedelta,
avoid_further_combat: bool = False,
) -> None:
self.flight.set_state(self.previous_state)
self.previous_state.avoid_further_combat = avoid_further_combat
self.previous_state.on_game_tick(events, time, elapsed_time)
@property
def in_combat(self) -> bool:

View File

@ -49,7 +49,7 @@ class AircraftSimulation:
still_active = []
for combat in self.combats:
if combat.on_game_tick(duration, self.results, events):
if combat.on_game_tick(time, duration, self.results, events):
events.end_combat(combat)
else:
still_active.append(combat)

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import logging
import random
from datetime import timedelta
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from shapely.ops import unary_union
@ -61,7 +61,13 @@ class AirCombat(JoinableCombat):
def describe(self) -> str:
return f"in air-to-air combat"
def resolve(self, results: SimulationResults, events: GameUpdateEvents) -> None:
def resolve(
self,
results: SimulationResults,
events: GameUpdateEvents,
time: datetime,
elapsed_time: timedelta,
) -> None:
blue = []
red = []
for flight in self.flights:
@ -95,4 +101,4 @@ class AirCombat(JoinableCombat):
if random.random() >= 0.5:
flight.kill(results, events)
else:
flight.state.exit_combat()
flight.state.exit_combat(events, time, elapsed_time)

View File

@ -2,11 +2,12 @@ from __future__ import annotations
import logging
from collections.abc import Iterator
from datetime import timedelta
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from .frozencombat import FrozenCombat
from .. import GameUpdateEvents
from ...ato.flightstate import InCombat
if TYPE_CHECKING:
from game.ato import Flight
@ -27,8 +28,18 @@ class AtIp(FrozenCombat):
def iter_flights(self) -> Iterator[Flight]:
yield self.flight
def resolve(self, results: SimulationResults, events: GameUpdateEvents) -> None:
def resolve(
self,
results: SimulationResults,
events: GameUpdateEvents,
time: datetime,
elapsed_time: timedelta,
) -> None:
logging.debug(
f"{self.flight} attack on {self.flight.package.target} auto-resolved with "
"mission failure but no losses"
)
assert isinstance(self.flight.state, InCombat)
self.flight.state.exit_combat(
events, time, elapsed_time, avoid_further_combat=True
)

View File

@ -95,7 +95,7 @@ class CombatInitiator:
if not flight.state.in_flight:
return None
if flight.state.is_at_ip:
if flight.state.is_at_ip and not flight.state.avoid_further_combat:
return AtIp(timedelta(minutes=1), flight)
position = flight.state.estimate_position()

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import logging
import random
from collections.abc import Iterator
from datetime import timedelta
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from game.ato.flightstate import InCombat
@ -37,7 +37,13 @@ class DefendingSam(FrozenCombat):
def iter_flights(self) -> Iterator[Flight]:
yield self.flight
def resolve(self, results: SimulationResults, events: GameUpdateEvents) -> None:
def resolve(
self,
results: SimulationResults,
events: GameUpdateEvents,
time: datetime,
elapsed_time: timedelta,
) -> None:
assert isinstance(self.flight.state, InCombat)
if random.random() >= 0.5:
logging.debug(f"Air defense combat auto-resolved with {self.flight} lost")
@ -46,4 +52,4 @@ class DefendingSam(FrozenCombat):
logging.debug(
f"Air defense combat auto-resolved with {self.flight} surviving"
)
self.flight.state.exit_combat()
self.flight.state.exit_combat(events, time, elapsed_time)

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import uuid
from abc import ABC, abstractmethod
from collections.abc import Iterator
from datetime import timedelta
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from game.ato.flightstate import InCombat, InFlight
@ -21,16 +21,26 @@ class FrozenCombat(ABC):
self.elapsed_time = timedelta()
def on_game_tick(
self, duration: timedelta, results: SimulationResults, events: GameUpdateEvents
self,
time: datetime,
duration: timedelta,
results: SimulationResults,
events: GameUpdateEvents,
) -> bool:
self.elapsed_time += duration
if self.elapsed_time >= self.freeze_duration:
self.resolve(results, events)
self.resolve(results, events, time, self.elapsed_time)
return True
return False
@abstractmethod
def resolve(self, results: SimulationResults, events: GameUpdateEvents) -> None:
def resolve(
self,
results: SimulationResults,
events: GameUpdateEvents,
time: datetime,
elapsed_time: timedelta,
) -> None:
...
@abstractmethod