Fixes an unlikely bug with JTAC laser code allocation (#1477)

* Fixes an unlikely bug with JTAC laser code allocation, allows for future allocation of codes to a/c with TGPs

* Fixing typing issues

* Changelog
This commit is contained in:
bgreman 2021-07-31 18:44:16 -04:00 committed by GitHub
parent 0d6f420f97
commit fc45c3b98c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 1 deletions

View File

@ -49,6 +49,7 @@ Saves from 4.0.0 are compatible with 4.1.0.
* **[Mission Generation]** Prevent the creation of a transfer order with 0 units for a rare situtation when a point was captured.
* **[Mission Generation]** Planned transfers which will be impossible after a base capture will no longer prevent the mission result submit.
* **[Mission Generation]** Fix occasional KeyError preventing mission generation when all units of the same type in a convoy were killed.
* **[Mission Generation]** Fixed a potential bug with laser code generation where it would generate invalid codes.
* **[UI]** Statistics window tick marks are now always integers.
* **[UI]** Statistics window now shows the correct info for the turn
* **[UI]** Toggling custom loadout for an aircraft with no preset loadouts no longer breaks the flight.

View File

@ -29,6 +29,7 @@ from gen.environmentgen import EnvironmentGenerator
from gen.forcedoptionsgen import ForcedOptionsGenerator
from gen.groundobjectsgen import GroundObjectsGenerator
from gen.kneeboard import KneeboardGenerator
from gen.lasercoderegistry import LaserCodeRegistry
from gen.naming import namegen
from gen.radios import RadioFrequency, RadioRegistry
from gen.tacan import TacanRegistry
@ -50,6 +51,7 @@ class Operation:
groundobjectgen: GroundObjectsGenerator
radio_registry: RadioRegistry
tacan_registry: TacanRegistry
laser_code_registry: LaserCodeRegistry
game: Game
trigger_radius = TRIGGER_RADIUS_MEDIUM
is_quick = None
@ -192,6 +194,10 @@ class Operation:
for frequency in unique_map_frequencies:
cls.radio_registry.reserve(frequency)
@classmethod
def create_laser_code_registry(cls) -> None:
cls.laser_code_registry = LaserCodeRegistry()
@classmethod
def assign_channels_to_flights(
cls, flights: List[FlightData], air_support: AirSupport
@ -282,6 +288,7 @@ class Operation:
cls.air_support = AirSupport()
cls.create_unit_map()
cls.create_radio_registries()
cls.create_laser_code_registry()
# Set mission time and weather conditions.
EnvironmentGenerator(cls.current_mission, cls.game.conditions).generate()
cls._generate_ground_units()
@ -399,6 +406,7 @@ class Operation:
cls.unit_map,
cls.radio_registry,
cls.air_support,
cls.laser_code_registry,
)
ground_conflict_gen.generate()

View File

@ -44,6 +44,7 @@ from .airsupport import AirSupport, JtacInfo
from .callsigns import callsign_for_support_unit
from .conflictgen import Conflict
from .ground_forces.combat_stance import CombatStance
from .lasercoderegistry import LaserCodeRegistry
from .naming import namegen
from .radios import MHz, RadioFrequency, RadioRegistry
@ -81,6 +82,7 @@ class GroundConflictGenerator:
unit_map: UnitMap,
radio_registry: RadioRegistry,
air_support: AirSupport,
laser_code_registry: LaserCodeRegistry,
) -> None:
self.mission = mission
self.conflict = conflict
@ -92,6 +94,7 @@ class GroundConflictGenerator:
self.unit_map = unit_map
self.radio_registry = radio_registry
self.air_support = air_support
self.laser_code_registry = laser_code_registry
def generate(self) -> None:
position = Conflict.frontline_position(
@ -140,7 +143,7 @@ class GroundConflictGenerator:
# Add JTAC
if self.game.blue.faction.has_jtac:
n = "JTAC" + str(self.conflict.blue_cp.id) + str(self.conflict.red_cp.id)
code = 1688 - len(self.air_support.jtacs)
code: int = self.laser_code_registry.get_next_laser_code()
freq = self.radio_registry.alloc_uhf()
utype = self.game.blue.faction.jtac_unit

37
gen/lasercoderegistry.py Normal file
View File

@ -0,0 +1,37 @@
from collections import deque
from typing import Iterator
class OutOfLaserCodesError(RuntimeError):
def __init__(self) -> None:
super().__init__(
f"All JTAC laser codes have been allocated. No available codes."
)
class LaserCodeRegistry:
def __init__(self) -> None:
self.allocated_codes: set[int] = set()
self.allocator: Iterator[int] = LaserCodeRegistry.__laser_code_generator()
def get_next_laser_code(self) -> int:
try:
while (code := next(self.allocator)) in self.allocated_codes:
pass
self.allocated_codes.add(code)
return code
except StopIteration:
raise OutOfLaserCodesError
@staticmethod
def __laser_code_generator() -> Iterator[int]:
# Valid laser codes are as follows
# First digit is always 1
# Second digit is 5-7
# Third and fourth digits are 1 - 8
# We iterate backward (reversed()) so that 1687 follows 1688
q = deque(int(oct(code)[2:]) + 11 for code in reversed(range(0o1500, 0o2000)))
# We start with the default of 1688 and wrap around when we reach the end
q.rotate(-q.index(1688))
return iter(q)