mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
number of fixes
This commit is contained in:
parent
8a783625ce
commit
064b9ba877
2
.idea/dcs_pmcliberation.iml
generated
2
.idea/dcs_pmcliberation.iml
generated
@ -4,7 +4,7 @@
|
|||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.6" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.6 (venv)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="TestRunnerService">
|
<component name="TestRunnerService">
|
||||||
|
|||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (venv)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
14
game/db.py
14
game/db.py
@ -15,7 +15,7 @@ PRICES = {
|
|||||||
A_10A: 18,
|
A_10A: 18,
|
||||||
A_10C: 20,
|
A_10C: 20,
|
||||||
|
|
||||||
F_A_18C: 18,
|
FA_18C_hornet: 18,
|
||||||
AV8BNA: 15,
|
AV8BNA: 15,
|
||||||
|
|
||||||
Su_27: 30,
|
Su_27: 30,
|
||||||
@ -23,13 +23,15 @@ PRICES = {
|
|||||||
F_15C: 30,
|
F_15C: 30,
|
||||||
M_2000C: 11,
|
M_2000C: 11,
|
||||||
|
|
||||||
MiG_15bis: 6,
|
|
||||||
MiG_21Bis: 13,
|
MiG_21Bis: 13,
|
||||||
MiG_29A: 23,
|
MiG_29A: 23,
|
||||||
|
|
||||||
IL_76MD: 13,
|
IL_76MD: 13,
|
||||||
S_3B_Tanker: 13,
|
S_3B_Tanker: 13,
|
||||||
|
|
||||||
|
A_50: 8,
|
||||||
|
E_3A: 8,
|
||||||
|
|
||||||
# armor
|
# armor
|
||||||
|
|
||||||
Armor.MBT_T_55: 4,
|
Armor.MBT_T_55: 4,
|
||||||
@ -47,12 +49,13 @@ PRICES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UNIT_BY_TASK = {
|
UNIT_BY_TASK = {
|
||||||
FighterSweep: [Su_27, Su_33, Su_25, F_15C, MiG_15bis, MiG_21Bis, MiG_29A, F_A_18C, AV8BNA],
|
FighterSweep: [Su_27, Su_33, FA_18C_hornet, F_15C, MiG_21Bis, MiG_29A, F_A_18C, AV8BNA],
|
||||||
CAS: [Su_25T, A_10A, A_10C, ],
|
CAS: [Su_25T, A_10A, A_10C, ],
|
||||||
CAP: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ],
|
CAP: [Armor.MBT_T_90, Armor.MBT_T_80U, Armor.MBT_T_55, Armor.MBT_M1A2_Abrams, Armor.MBT_M60A3_Patton, Armor.ATGM_M1134_Stryker, Armor.APC_BTR_80, ],
|
||||||
AirDefence: [AirDefence.AAA_ZU_23_on_Ural_375, AirDefence.SAM_Avenger_M1097 ],
|
AirDefence: [AirDefence.AAA_ZU_23_on_Ural_375, AirDefence.SAM_Avenger_M1097 ],
|
||||||
Transport: [IL_76MD, S_3B_Tanker, ],
|
Transport: [IL_76MD, S_3B_Tanker, ],
|
||||||
Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ],
|
Carriage: [CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov, ],
|
||||||
|
AWACS: [E_3A, A_50, ],
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT_BY_COUNTRY = {
|
UNIT_BY_COUNTRY = {
|
||||||
@ -61,9 +64,9 @@ UNIT_BY_COUNTRY = {
|
|||||||
Su_27,
|
Su_27,
|
||||||
Su_33,
|
Su_33,
|
||||||
Su_25,
|
Su_25,
|
||||||
MiG_15bis,
|
|
||||||
MiG_21Bis,
|
MiG_21Bis,
|
||||||
MiG_29A,
|
MiG_29A,
|
||||||
|
A_50,
|
||||||
AirDefence.AAA_ZU_23_on_Ural_375,
|
AirDefence.AAA_ZU_23_on_Ural_375,
|
||||||
Armor.APC_BTR_80,
|
Armor.APC_BTR_80,
|
||||||
Armor.MBT_T_90,
|
Armor.MBT_T_90,
|
||||||
@ -74,8 +77,9 @@ UNIT_BY_COUNTRY = {
|
|||||||
|
|
||||||
"USA": [F_15C,
|
"USA": [F_15C,
|
||||||
A_10C,
|
A_10C,
|
||||||
F_A_18C,
|
FA_18C_hornet,
|
||||||
AV8BNA,
|
AV8BNA,
|
||||||
|
E_3A,
|
||||||
Armor.MBT_M1A2_Abrams,
|
Armor.MBT_M1A2_Abrams,
|
||||||
Armor.MBT_M60A3_Patton,
|
Armor.MBT_M60A3_Patton,
|
||||||
Armor.ATGM_M1134_Stryker,
|
Armor.ATGM_M1134_Stryker,
|
||||||
|
|||||||
@ -10,12 +10,12 @@ class Event:
|
|||||||
difficulty = 1 # type: int
|
difficulty = 1 # type: int
|
||||||
BONUS_BASE = 0
|
BONUS_BASE = 0
|
||||||
|
|
||||||
def __init__(self, attacker_name: str, defender_name: str, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
def __init__(self, attacker_name: str, defender_name: str, from_cp: ControlPoint, to_cp: ControlPoint, game):
|
||||||
self.attacker_name = attacker_name
|
self.attacker_name = attacker_name
|
||||||
self.defender_name = defender_name
|
self.defender_name = defender_name
|
||||||
self.to_cp = to_cp
|
self.to_cp = to_cp
|
||||||
self.from_cp = from_cp
|
self.from_cp = from_cp
|
||||||
self.theater = theater
|
self.game = game
|
||||||
|
|
||||||
def bonus(self) -> int:
|
def bonus(self) -> int:
|
||||||
return math.ceil(math.log(self.difficulty, DIFFICULTY_LOG_BASE) * self.BONUS_BASE)
|
return math.ceil(math.log(self.difficulty, DIFFICULTY_LOG_BASE) * self.BONUS_BASE)
|
||||||
@ -28,6 +28,7 @@ class Event:
|
|||||||
self.operation.generate()
|
self.operation.generate()
|
||||||
self.operation.mission.save("build/nextturn.miz")
|
self.operation.mission.save("build/nextturn.miz")
|
||||||
|
|
||||||
|
def generate_quick(self):
|
||||||
self.operation.prepare(is_quick=True)
|
self.operation.prepare(is_quick=True)
|
||||||
self.operation.generate()
|
self.operation.generate()
|
||||||
self.operation.mission.save('build/nextturn_quick.miz')
|
self.operation.mission.save('build/nextturn_quick.miz')
|
||||||
@ -91,7 +92,7 @@ class GroundInterceptEvent(Event):
|
|||||||
typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1)
|
typecount = max(math.floor(self.difficulty * self.TARGET_AMOUNT_FACTOR), 1)
|
||||||
self.targets = {unittype: typecount for unittype in unittypes}
|
self.targets = {unittype: typecount for unittype in unittypes}
|
||||||
|
|
||||||
op = GroundInterceptOperation(theater=self.theater,
|
op = GroundInterceptOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
attacker_clients=clients,
|
||||||
@ -128,7 +129,7 @@ class InterceptEvent(Event):
|
|||||||
|
|
||||||
if self.is_successfull(debriefing):
|
if self.is_successfull(debriefing):
|
||||||
if self.from_cp.is_global:
|
if self.from_cp.is_global:
|
||||||
for cp in self.theater.enemy_points():
|
for cp in self.game.theater.enemy_points():
|
||||||
cp.base.affect_strength(-self.GLOBAL_STRENGTH_INFLUENCE)
|
cp.base.affect_strength(-self.GLOBAL_STRENGTH_INFLUENCE)
|
||||||
else:
|
else:
|
||||||
self.to_cp.base.affect_strength(self.STRENGTH_INFLUENCE * float(self.from_cp.captured and -1 or 1))
|
self.to_cp.base.affect_strength(self.STRENGTH_INFLUENCE * float(self.from_cp.captured and -1 or 1))
|
||||||
@ -146,7 +147,7 @@ class InterceptEvent(Event):
|
|||||||
|
|
||||||
airdefense_unit = db.find_unittype(AirDefence, self.defender_name)[0]
|
airdefense_unit = db.find_unittype(AirDefence, self.defender_name)[0]
|
||||||
|
|
||||||
op = InterceptOperation(theater=self.theater,
|
op = InterceptOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
attacker_clients=clients,
|
||||||
@ -166,7 +167,7 @@ class InterceptEvent(Event):
|
|||||||
self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name))
|
self.transport_unit = random.choice(db.find_unittype(Transport, self.defender_name))
|
||||||
assert self.transport_unit is not None
|
assert self.transport_unit is not None
|
||||||
|
|
||||||
op = InterceptOperation(theater=self.theater,
|
op = InterceptOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients={},
|
attacker_clients={},
|
||||||
@ -191,7 +192,9 @@ class CaptureEvent(Event):
|
|||||||
return "Attack from {} to {}".format(self.from_cp, self.to_cp)
|
return "Attack from {} to {}".format(self.from_cp, self.to_cp)
|
||||||
|
|
||||||
def is_successfull(self, debriefing: Debriefing):
|
def is_successfull(self, debriefing: Debriefing):
|
||||||
attackers_success = len(debriefing.destroyed_units[self.defender_name]) > len(debriefing.destroyed_units[self.attacker_name])
|
alive_attackers = sum(debriefing.alive_units[self.attacker_name].values())
|
||||||
|
alive_defenders = sum(debriefing.alive_units[self.defender_name].values())
|
||||||
|
attackers_success = alive_attackers > alive_defenders
|
||||||
if self.from_cp.captured:
|
if self.from_cp.captured:
|
||||||
return attackers_success
|
return attackers_success
|
||||||
else:
|
else:
|
||||||
@ -219,7 +222,7 @@ class CaptureEvent(Event):
|
|||||||
escort = self.from_cp.base.scramble_sweep(self.to_cp)
|
escort = self.from_cp.base.scramble_sweep(self.to_cp)
|
||||||
attackers = self.from_cp.base.assemble_cap(self.to_cp)
|
attackers = self.from_cp.base.assemble_cap(self.to_cp)
|
||||||
|
|
||||||
op = CaptureOperation(theater=self.theater,
|
op = CaptureOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients={},
|
attacker_clients={},
|
||||||
@ -239,7 +242,7 @@ class CaptureEvent(Event):
|
|||||||
def player_attacking(self, cas: db.PlaneDict, escort: db.PlaneDict, armor: db.ArmorDict, clients: db.PlaneDict):
|
def player_attacking(self, cas: db.PlaneDict, escort: db.PlaneDict, armor: db.ArmorDict, clients: db.PlaneDict):
|
||||||
interceptors = self.to_cp.base.scramble_sweep(for_target=self.to_cp)
|
interceptors = self.to_cp.base.scramble_sweep(for_target=self.to_cp)
|
||||||
|
|
||||||
op = CaptureOperation(theater=self.theater,
|
op = CaptureOperation(game=self.game,
|
||||||
attacker_name=self.attacker_name,
|
attacker_name=self.attacker_name,
|
||||||
defender_name=self.defender_name,
|
defender_name=self.defender_name,
|
||||||
attacker_clients=clients,
|
attacker_clients=clients,
|
||||||
@ -261,12 +264,12 @@ class UnitsDeliveryEvent(Event):
|
|||||||
informational = True
|
informational = True
|
||||||
units = None # type: typing.Dict[UnitType, int]
|
units = None # type: typing.Dict[UnitType, int]
|
||||||
|
|
||||||
def __init__(self, attacker_name: str, defender_name: str, from_cp: ControlPoint, to_cp: ControlPoint, theater: ConflictTheater):
|
def __init__(self, attacker_name: str, defender_name: str, from_cp: ControlPoint, to_cp: ControlPoint, game):
|
||||||
super(UnitsDeliveryEvent, self).__init__(attacker_name=attacker_name,
|
super(UnitsDeliveryEvent, self).__init__(attacker_name=attacker_name,
|
||||||
defender_name=defender_name,
|
defender_name=defender_name,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=theater)
|
game=game)
|
||||||
|
|
||||||
self.units = {}
|
self.units = {}
|
||||||
|
|
||||||
|
|||||||
23
game/game.py
23
game/game.py
@ -27,7 +27,7 @@ PLAYER_GROUNDINTERCEPT_PROBABILITY_BASE = 30
|
|||||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 50
|
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE = 50
|
||||||
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2
|
PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG = 2
|
||||||
|
|
||||||
PLAYER_BUDGET_INITIAL = 60
|
PLAYER_BUDGET_INITIAL = 90
|
||||||
PLAYER_BUDGET_BASE = 20
|
PLAYER_BUDGET_BASE = 20
|
||||||
PLAYER_BUDGET_IMPORTANCE_LOG = 2
|
PLAYER_BUDGET_IMPORTANCE_LOG = 2
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ class Game:
|
|||||||
defender_name=self.enemy,
|
defender_name=self.enemy,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
|
|
||||||
def _generate_enemy_caps(self):
|
def _generate_enemy_caps(self):
|
||||||
for from_cp, to_cp in self.theater.conflicts(False):
|
for from_cp, to_cp in self.theater.conflicts(False):
|
||||||
@ -65,7 +65,7 @@ class Game:
|
|||||||
defender_name=self.player,
|
defender_name=self.player,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
break
|
break
|
||||||
|
|
||||||
def _generate_interceptions(self):
|
def _generate_interceptions(self):
|
||||||
@ -79,7 +79,7 @@ class Game:
|
|||||||
defender_name=self.player,
|
defender_name=self.player,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
enemy_interception = True
|
enemy_interception = True
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -87,6 +87,9 @@ class Game:
|
|||||||
if enemy_interception:
|
if enemy_interception:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if to_cp.is_global:
|
||||||
|
continue
|
||||||
|
|
||||||
if to_cp in self.theater.conflicts(False):
|
if to_cp in self.theater.conflicts(False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -97,7 +100,7 @@ class Game:
|
|||||||
defender_name=self.player,
|
defender_name=self.player,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
enemy_interception = True
|
enemy_interception = True
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -107,7 +110,7 @@ class Game:
|
|||||||
defender_name=self.enemy,
|
defender_name=self.enemy,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
break
|
break
|
||||||
|
|
||||||
def _generate_groundinterceptions(self):
|
def _generate_groundinterceptions(self):
|
||||||
@ -117,7 +120,7 @@ class Game:
|
|||||||
defender_name=self.enemy,
|
defender_name=self.enemy,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
break
|
break
|
||||||
|
|
||||||
def _generate_globalinterceptions(self):
|
def _generate_globalinterceptions(self):
|
||||||
@ -129,7 +132,7 @@ class Game:
|
|||||||
defender_name=self.enemy,
|
defender_name=self.enemy,
|
||||||
from_cp=from_cp,
|
from_cp=from_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater))
|
game=self))
|
||||||
break
|
break
|
||||||
|
|
||||||
def _commision_units(self, cp: ControlPoint):
|
def _commision_units(self, cp: ControlPoint):
|
||||||
@ -160,7 +163,7 @@ class Game:
|
|||||||
defender_name=self.player,
|
defender_name=self.player,
|
||||||
from_cp=to_cp,
|
from_cp=to_cp,
|
||||||
to_cp=to_cp,
|
to_cp=to_cp,
|
||||||
theater=self.theater)
|
game=self)
|
||||||
self.events.append(event)
|
self.events.append(event)
|
||||||
return event
|
return event
|
||||||
|
|
||||||
@ -170,7 +173,9 @@ class Game:
|
|||||||
|
|
||||||
def initiate_event(self, event: Event):
|
def initiate_event(self, event: Event):
|
||||||
assert event in self.events
|
assert event in self.events
|
||||||
|
|
||||||
event.generate()
|
event.generate()
|
||||||
|
event.generate_quick()
|
||||||
|
|
||||||
def finish_event(self, event: Event, debriefing: Debriefing):
|
def finish_event(self, event: Event, debriefing: Debriefing):
|
||||||
event.commit(debriefing)
|
event.commit(debriefing)
|
||||||
|
|||||||
@ -11,7 +11,8 @@ from gen.envsettingsgen import *
|
|||||||
|
|
||||||
|
|
||||||
class Operation:
|
class Operation:
|
||||||
starting_position = None # type: db.StartingPosition
|
attackers_starting_position = None # type: db.StartingPosition
|
||||||
|
defenders_starting_position = None # type: db.StartingPosition
|
||||||
mission = None # type: dcs.Mission
|
mission = None # type: dcs.Mission
|
||||||
conflict = None # type: Conflict
|
conflict = None # type: Conflict
|
||||||
armorgen = None # type: ArmorConflictGenerator
|
armorgen = None # type: ArmorConflictGenerator
|
||||||
@ -22,14 +23,14 @@ class Operation:
|
|||||||
envgen = None # type: EnvironmentSettingsGenerator
|
envgen = None # type: EnvironmentSettingsGenerator
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
theater: ConflictTheater,
|
game,
|
||||||
attacker_name: str,
|
attacker_name: str,
|
||||||
defender_name: str,
|
defender_name: str,
|
||||||
attacker_clients: db.PlaneDict,
|
attacker_clients: db.PlaneDict,
|
||||||
defender_clients: db.PlaneDict,
|
defender_clients: db.PlaneDict,
|
||||||
from_cp: ControlPoint,
|
from_cp: ControlPoint,
|
||||||
to_cp: ControlPoint = None):
|
to_cp: ControlPoint = None):
|
||||||
self.theater = theater
|
self.game = game
|
||||||
self.attacker_name = attacker_name
|
self.attacker_name = attacker_name
|
||||||
self.defender_name = defender_name
|
self.defender_name = defender_name
|
||||||
self.attacker_clients = attacker_clients
|
self.attacker_clients = attacker_clients
|
||||||
@ -45,14 +46,19 @@ class Operation:
|
|||||||
self.airgen = AircraftConflictGenerator(mission, conflict)
|
self.airgen = AircraftConflictGenerator(mission, conflict)
|
||||||
self.aagen = AAConflictGenerator(mission, conflict)
|
self.aagen = AAConflictGenerator(mission, conflict)
|
||||||
self.shipgen = ShipGenerator(mission, conflict)
|
self.shipgen = ShipGenerator(mission, conflict)
|
||||||
self.envgen = EnvironmentSettingsGenerator(mission)
|
self.envgen = EnvironmentSettingsGenerator(mission, self.game)
|
||||||
|
|
||||||
player_name = self.from_cp.captured and self.attacker_name or self.defender_name
|
player_name = self.from_cp.captured and self.attacker_name or self.defender_name
|
||||||
enemy_name = self.from_cp.captured and self.defender_name or self.attacker_name
|
enemy_name = self.from_cp.captured and self.defender_name or self.attacker_name
|
||||||
self.extra_aagen = ExtraAAConflictGenerator(mission, conflict, self.theater, player_name, enemy_name)
|
self.extra_aagen = ExtraAAConflictGenerator(mission, conflict, self.game, player_name, enemy_name)
|
||||||
|
|
||||||
def prepare(self, is_quick: bool):
|
def prepare(self, is_quick: bool):
|
||||||
self.starting_position = is_quick and self.from_cp.at or None
|
if is_quick:
|
||||||
|
self.attackers_starting_position = None
|
||||||
|
self.defenders_starting_position = None
|
||||||
|
else:
|
||||||
|
self.attackers_starting_position = self.from_cp.at
|
||||||
|
self.defenders_starting_position = self.to_cp and self.to_cp.at or None
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.extra_aagen.generate()
|
self.extra_aagen.generate()
|
||||||
@ -97,13 +103,14 @@ class CaptureOperation(Operation):
|
|||||||
mission.country(self.defender_name)))
|
mission.country(self.defender_name)))
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
super(CaptureOperation, self).generate()
|
self.envgen.generate()
|
||||||
self.armorgen.generate(self.attack, self.defense)
|
self.armorgen.generate(self.attack, self.defense)
|
||||||
self.aagen.generate(self.aa)
|
self.aagen.generate(self.aa)
|
||||||
self.airgen.generate_defense(self.intercept, clients=self.defender_clients)
|
|
||||||
|
|
||||||
self.airgen.generate_cas(self.cas, clients=self.attacker_clients, at=self.starting_position)
|
self.airgen.generate_defense(self.intercept, clients=self.defender_clients, at=self.defenders_starting_position)
|
||||||
self.airgen.generate_cas_escort(self.escort, clients=self.attacker_clients, at=self.starting_position)
|
|
||||||
|
self.airgen.generate_cas(self.cas, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||||
|
self.airgen.generate_cas_escort(self.escort, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||||
|
|
||||||
|
|
||||||
class InterceptOperation(Operation):
|
class InterceptOperation(Operation):
|
||||||
@ -126,15 +133,11 @@ class InterceptOperation(Operation):
|
|||||||
super(InterceptOperation, self).prepare(is_quick)
|
super(InterceptOperation, self).prepare(is_quick)
|
||||||
mission = dcs.Mission()
|
mission = dcs.Mission()
|
||||||
|
|
||||||
heading = self.from_cp.position.heading_between_point(self.to_cp.position)
|
|
||||||
distance = self.from_cp.position.distance_to_point(self.to_cp.position)
|
|
||||||
position = self.from_cp.position.point_from_heading(heading, distance/2)
|
|
||||||
conflict = Conflict.intercept_conflict(
|
conflict = Conflict.intercept_conflict(
|
||||||
attacker=mission.country(self.attacker_name),
|
attacker=mission.country(self.attacker_name),
|
||||||
defender=mission.country(self.defender_name),
|
defender=mission.country(self.defender_name),
|
||||||
position=position,
|
from_cp=self.from_cp,
|
||||||
heading=randint(0, 360),
|
to_cp=self.to_cp
|
||||||
radials=ALL_RADIALS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.initialize(mission=mission,
|
self.initialize(mission=mission,
|
||||||
@ -144,14 +147,13 @@ class InterceptOperation(Operation):
|
|||||||
super(InterceptOperation, self).generate()
|
super(InterceptOperation, self).generate()
|
||||||
self.airgen.generate_transport(self.transport, self.to_cp.at)
|
self.airgen.generate_transport(self.transport, self.to_cp.at)
|
||||||
self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients)
|
self.airgen.generate_transport_escort(self.escort, clients=self.defender_clients)
|
||||||
self.aagen.generate(self.airdefense)
|
|
||||||
|
|
||||||
if self.from_cp.is_global:
|
if self.from_cp.is_global:
|
||||||
ship = self.shipgen.generate(type=db.find_unittype(Carriage, self.attacker_name)[0],
|
ship = self.shipgen.generate(type=db.find_unittype(Carriage, self.attacker_name)[0],
|
||||||
at=self.from_cp.at)
|
at=self.from_cp.at)
|
||||||
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=ship)
|
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=ship)
|
||||||
else:
|
else:
|
||||||
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.starting_position)
|
self.airgen.generate_interception(self.interceptors, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||||
|
|
||||||
|
|
||||||
class GroundInterceptOperation(Operation):
|
class GroundInterceptOperation(Operation):
|
||||||
@ -167,7 +169,7 @@ class GroundInterceptOperation(Operation):
|
|||||||
super(GroundInterceptOperation, self).prepare(is_quick)
|
super(GroundInterceptOperation, self).prepare(is_quick)
|
||||||
mission = dcs.Mission()
|
mission = dcs.Mission()
|
||||||
conflict = Conflict.ground_intercept_conflict(
|
conflict = Conflict.ground_intercept_conflict(
|
||||||
attacker=mission.country(self.defender_name),
|
attacker=mission.country(self.attacker_name),
|
||||||
defender=mission.country(self.defender_name),
|
defender=mission.country(self.defender_name),
|
||||||
position=self.position,
|
position=self.position,
|
||||||
heading=randint(0, 360),
|
heading=randint(0, 360),
|
||||||
@ -179,5 +181,5 @@ class GroundInterceptOperation(Operation):
|
|||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
super(GroundInterceptOperation, self).generate()
|
super(GroundInterceptOperation, self).generate()
|
||||||
self.airgen.generate_cas(self.strikegroup, clients=self.attacker_clients, at=self.starting_position)
|
self.airgen.generate_cas(self.strikegroup, clients=self.attacker_clients, at=self.attackers_starting_position)
|
||||||
self.armorgen.generate({}, self.target)
|
self.armorgen.generate({}, self.target)
|
||||||
|
|||||||
@ -29,15 +29,18 @@ class AAConflictGenerator:
|
|||||||
|
|
||||||
|
|
||||||
class ExtraAAConflictGenerator:
|
class ExtraAAConflictGenerator:
|
||||||
def __init__(self, mission: Mission, conflict: Conflict, theater: ConflictTheater, player_name: Country, enemy_name: Country):
|
def __init__(self, mission: Mission, conflict: Conflict, game, player_name: Country, enemy_name: Country):
|
||||||
self.mission = mission
|
self.mission = mission
|
||||||
self.theater = theater
|
self.game = game
|
||||||
self.conflict = conflict
|
self.conflict = conflict
|
||||||
self.player_name = player_name
|
self.player_name = player_name
|
||||||
self.enemy_name = enemy_name
|
self.enemy_name = enemy_name
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
for cp in self.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
|
if cp.is_global:
|
||||||
|
continue
|
||||||
|
|
||||||
if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MIN_DISTANCE:
|
if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MIN_DISTANCE:
|
||||||
country_name = cp.captured and self.player_name or self.enemy_name
|
country_name = cp.captured and self.player_name or self.enemy_name
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@ INTERCEPT_ATTACKERS_HEADING = -45, 45
|
|||||||
INTERCEPT_DEFENDERS_HEADING = -10, 10
|
INTERCEPT_DEFENDERS_HEADING = -10, 10
|
||||||
INTERCEPT_ATTACKERS_DISTANCE = 60000
|
INTERCEPT_ATTACKERS_DISTANCE = 60000
|
||||||
INTERCEPT_DEFENDERS_DISTANCE = 30000
|
INTERCEPT_DEFENDERS_DISTANCE = 30000
|
||||||
|
INTERCEPT_MAX_DISTANCE = 45000
|
||||||
|
|
||||||
|
|
||||||
class Conflict:
|
class Conflict:
|
||||||
@ -56,8 +57,13 @@ class Conflict:
|
|||||||
return instance
|
return instance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def intercept_conflict(self, attacker: Country, defender: Country, position: Point, heading: int, radials: typing.List[int]):
|
def intercept_conflict(self, attacker: Country, defender: Country, from_cp, to_cp):
|
||||||
from theater.conflicttheater import SIZE_REGULAR
|
from theater.conflicttheater import SIZE_REGULAR
|
||||||
|
from theater.conflicttheater import ALL_RADIALS
|
||||||
|
|
||||||
|
heading = from_cp.position.heading_between_point(to_cp.position)
|
||||||
|
distance = min(from_cp.position.distance_to_point(to_cp.position) / 2, INTERCEPT_MAX_DISTANCE)
|
||||||
|
position = from_cp.position.point_from_heading(heading, distance)
|
||||||
|
|
||||||
instance = self()
|
instance = self()
|
||||||
instance.attackers_side = attacker
|
instance.attackers_side = attacker
|
||||||
@ -65,7 +71,7 @@ class Conflict:
|
|||||||
|
|
||||||
instance.position = position
|
instance.position = position
|
||||||
instance.size = SIZE_REGULAR
|
instance.size = SIZE_REGULAR
|
||||||
instance.radials = radials
|
instance.radials = ALL_RADIALS
|
||||||
|
|
||||||
instance.air_attackers_location = instance.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, INTERCEPT_ATTACKERS_DISTANCE)
|
instance.air_attackers_location = instance.position.point_from_heading(random.randint(*INTERCEPT_ATTACKERS_HEADING) + heading, INTERCEPT_ATTACKERS_DISTANCE)
|
||||||
instance.air_defenders_location = instance.position.point_from_heading(random.randint(*INTERCEPT_DEFENDERS_HEADING) + heading, INTERCEPT_DEFENDERS_DISTANCE)
|
instance.air_defenders_location = instance.position.point_from_heading(random.randint(*INTERCEPT_DEFENDERS_HEADING) + heading, INTERCEPT_DEFENDERS_DISTANCE)
|
||||||
|
|||||||
@ -7,22 +7,34 @@ from theater.weatherforecast import WeatherForecast
|
|||||||
|
|
||||||
|
|
||||||
RANDOM_TIME = {
|
RANDOM_TIME = {
|
||||||
"night": 5,
|
"night": 0,
|
||||||
"dusk": 25,
|
"dusk": 5,
|
||||||
"down": 50,
|
"dawn": 35,
|
||||||
"noon": 75,
|
"noon": 75,
|
||||||
"day": 100,
|
"day": 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentSettingsGenerator:
|
class EnvironmentSettingsGenerator:
|
||||||
def __init__(self, mission: Mission):
|
def __init__(self, mission: Mission, game):
|
||||||
self.mission = mission
|
self.mission = mission
|
||||||
|
self.game = game
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.mission.random_weather = True
|
|
||||||
|
|
||||||
time_roll = random.randint(0, 100)
|
time_roll = random.randint(0, 100)
|
||||||
time_period = [k for k, v in RANDOM_TIME.items() if v > time_roll][-1]
|
time_period = None
|
||||||
self.mission.random_daytime(time_period)
|
for k, v in RANDOM_TIME.items():
|
||||||
|
if v >= time_roll:
|
||||||
|
time_period = k
|
||||||
|
break
|
||||||
|
|
||||||
|
self.mission.random_daytime(time_period)
|
||||||
|
self.mission.weather.random(self.mission.start_time, self.mission.terrain)
|
||||||
|
|
||||||
|
for cp in self.game.theater.controlpoints:
|
||||||
|
if cp.is_global:
|
||||||
|
continue
|
||||||
|
|
||||||
|
player_coalition = self.game.player == "USA" and "blue" or "red"
|
||||||
|
enemy_coalition = player_coalition == "blue" and "red" or "blue"
|
||||||
|
self.mission.terrain.airport_by_id(cp.at.id).set_coalition(cp.captured and player_coalition or enemy_coalition)
|
||||||
|
|||||||
@ -137,7 +137,7 @@ class Base:
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
target_array[unit_type] = target_array[unit_type] - count
|
target_array[unit_type] = max(target_array[unit_type] - count, 0)
|
||||||
if target_array[unit_type] == 0:
|
if target_array[unit_type] == 0:
|
||||||
del target_array[unit_type]
|
del target_array[unit_type]
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ COAST_HORIZONTAL = [315, 0, 45, ]
|
|||||||
|
|
||||||
|
|
||||||
class ConflictTheater:
|
class ConflictTheater:
|
||||||
|
terrain = None # type: dcs.terrain.Terrain
|
||||||
controlpoints = None # type: typing.Collection[ControlPoint]
|
controlpoints = None # type: typing.Collection[ControlPoint]
|
||||||
reference_points = None # type: typing.Dict
|
reference_points = None # type: typing.Dict
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,7 @@ class EventResultsMenu(Menu):
|
|||||||
Button(self.frame, text="Okay", command=self.dismiss).grid(columnspan=1, row=row); row += 1
|
Button(self.frame, text="Okay", command=self.dismiss).grid(columnspan=1, row=row); row += 1
|
||||||
|
|
||||||
def process_debriefing(self, debriefing: Debriefing):
|
def process_debriefing(self, debriefing: Debriefing):
|
||||||
|
self.debriefing = debriefing
|
||||||
debriefing.calculate_destroyed_units(mission=self.event.operation.mission,
|
debriefing.calculate_destroyed_units(mission=self.event.operation.mission,
|
||||||
player_name=self.game.player,
|
player_name=self.game.player,
|
||||||
enemy_name=self.game.enemy)
|
enemy_name=self.game.enemy)
|
||||||
|
|||||||
@ -44,8 +44,10 @@ class OverviewCanvas:
|
|||||||
title = cp.name
|
title = cp.name
|
||||||
font = ("Helvetica", 13)
|
font = ("Helvetica", 13)
|
||||||
|
|
||||||
self.canvas.create_text(coords[0]+1, coords[1]+1, text=title, fill='white', font=font)
|
id = self.canvas.create_text(coords[0]+1, coords[1]+1, text=title, fill='white', font=font)
|
||||||
self.canvas.create_text(coords[0], coords[1], text=title, font=font)
|
self.canvas.tag_bind(id, "<Button-1>", self.display(cp))
|
||||||
|
id = self.canvas.create_text(coords[0], coords[1], text=title, font=font)
|
||||||
|
self.canvas.tag_bind(id, "<Button-1>", self.display(cp))
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.canvas.delete(ALL)
|
self.canvas.delete(ALL)
|
||||||
@ -66,7 +68,7 @@ class OverviewCanvas:
|
|||||||
|
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
coords = self.cp_coordinates(cp)
|
coords = self.cp_coordinates(cp)
|
||||||
arc_size = 18 * math.pow(cp.importance, 1)
|
arc_size = 28 * math.pow(cp.importance, 1)
|
||||||
extent = max(cp.base.strength * 180, 10)
|
extent = max(cp.base.strength * 180, 10)
|
||||||
start = (180 - extent) / 2
|
start = (180 - extent) / 2
|
||||||
color = cp.captured and 'blue' or 'red'
|
color = cp.captured and 'blue' or 'red'
|
||||||
@ -78,7 +80,7 @@ class OverviewCanvas:
|
|||||||
start=start,
|
start=start,
|
||||||
extent=extent)
|
extent=extent)
|
||||||
self.canvas.tag_bind(cp_id, "<Button-1>", self.display(cp))
|
self.canvas.tag_bind(cp_id, "<Button-1>", self.display(cp))
|
||||||
self.create_cp_title((coords[0] + arc_size/2, coords[1] + arc_size/2), cp)
|
self.create_cp_title((coords[0] + arc_size/4, coords[1] + arc_size/4), cp)
|
||||||
|
|
||||||
units_title = "{}/{}/{}".format(cp.base.total_planes, cp.base.total_armor, cp.base.total_aa)
|
units_title = "{}/{}/{}".format(cp.base.total_planes, cp.base.total_armor, cp.base.total_aa)
|
||||||
self.canvas.create_text(coords[0], coords[1] - arc_size / 1.5, text=units_title, font=("Helvetica", 10))
|
self.canvas.create_text(coords[0], coords[1] - arc_size / 1.5, text=units_title, font=("Helvetica", 10))
|
||||||
|
|||||||
@ -7,6 +7,8 @@ from dcs.lua import parse
|
|||||||
from dcs.mission import Mission
|
from dcs.mission import Mission
|
||||||
|
|
||||||
from dcs.unitgroup import FlyingGroup
|
from dcs.unitgroup import FlyingGroup
|
||||||
|
from dcs.unit import Vehicle, VehicleType
|
||||||
|
from dcs.vehicles import vehicle_map
|
||||||
from dcs.unit import UnitType
|
from dcs.unit import UnitType
|
||||||
|
|
||||||
from game import db
|
from game import db
|
||||||
@ -20,20 +22,21 @@ class Debriefing:
|
|||||||
self.alive_units = alive_units # type: typing.Dict[str, typing.Dict[str, int]]
|
self.alive_units = alive_units # type: typing.Dict[str, typing.Dict[str, int]]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, path: str, mission: Mission):
|
def parse(cls, path: str):
|
||||||
with open(path, "r") as f:
|
with open(path, "r") as f:
|
||||||
table_string = f.read()
|
table_string = f.read()
|
||||||
table = parse.loads(table_string)
|
table = parse.loads(table_string)
|
||||||
units = table.get("debriefing", {}).get("world_state", {})
|
units = table.get("debriefing", {}).get("world_state", {})
|
||||||
alive_units = {}
|
alive_units = {}
|
||||||
|
|
||||||
for unit in units:
|
for unit in units.values():
|
||||||
type = unit["type"] # type: str
|
unit_type = unit["type"] # type: str
|
||||||
country_id = int(unit["country"])
|
country_id = int(unit["country"])
|
||||||
if type:
|
|
||||||
country_dict = alive_units.get(unit[country_id], {})
|
if type(unit_type) == str:
|
||||||
country_dict[type] = country_dict.get(type, 0) + 1
|
country_dict = alive_units.get(country_id, {})
|
||||||
alive_units[unit[country_id]] = country_dict
|
country_dict[unit_type] = country_dict.get(unit_type, 0) + 1
|
||||||
|
alive_units[country_id] = country_dict
|
||||||
|
|
||||||
return Debriefing(alive_units)
|
return Debriefing(alive_units)
|
||||||
|
|
||||||
@ -42,14 +45,20 @@ class Debriefing:
|
|||||||
result = {}
|
result = {}
|
||||||
for group in groups:
|
for group in groups:
|
||||||
for unit in group.units:
|
for unit in group.units:
|
||||||
result[unit.unit_type] = result.get(unit.unit_type, 0) + 1
|
unit_type = None
|
||||||
|
if isinstance(unit, Vehicle):
|
||||||
|
unit_type = vehicle_map[unit.type]
|
||||||
|
else:
|
||||||
|
unit_type = unit.unit_type
|
||||||
|
|
||||||
|
result[unit_type] = result.get(unit_type, 0) + 1
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def calculate_losses(all_units: typing.Dict[UnitType, int], alive_units: typing.Dict[str, int]) -> typing.Dict[UnitType, int]:
|
def calculate_losses(all_units: typing.Dict[UnitType, int], alive_units: typing.Dict[str, int]) -> typing.Dict[UnitType, int]:
|
||||||
result = {}
|
result = {}
|
||||||
for t, count in all_units.items():
|
for t, count in all_units.items():
|
||||||
result[t] = count - alive_units[db.unit_type_name(t)]
|
result[t] = max(count - alive_units.get(db.unit_type_name(t), 0), 0)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
player = mission.country(player_name)
|
player = mission.country(player_name)
|
||||||
@ -59,8 +68,8 @@ class Debriefing:
|
|||||||
enemy_units = count_groups(enemy.plane_group + enemy.vehicle_group)
|
enemy_units = count_groups(enemy.plane_group + enemy.vehicle_group)
|
||||||
|
|
||||||
self.destroyed_units = {
|
self.destroyed_units = {
|
||||||
player.name: calculate_losses(player_units, self.alive_units[player.id]),
|
player.name: calculate_losses(player_units, self.alive_units.get(player.id, {})),
|
||||||
enemy.name: calculate_losses(enemy_units, self.alive_units[enemy.id]),
|
enemy.name: calculate_losses(enemy_units, self.alive_units.get(enemy.id, {})),
|
||||||
}
|
}
|
||||||
|
|
||||||
def debriefing_directory_location() -> str:
|
def debriefing_directory_location() -> str:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user