New automatic de-briefing system implemented

This commit is contained in:
Khopa
2019-10-13 03:40:22 +02:00
parent 4365db0fae
commit 3f5f4f4bb1
18 changed files with 309 additions and 696 deletions

View File

@@ -1,441 +1,17 @@
import random
import math
from .conflictgen import *
from .naming import *
from dcs.mission import *
from dcs.mission import *
from .conflictgen import *
from .naming import *
DISTANCE_FACTOR = 0.5, 1
EXTRA_AA_MIN_DISTANCE = 50000
EXTRA_AA_MAX_DISTANCE = 150000
EXTRA_AA_POSITION_FROM_CP = 550
def num_sam_dead(sam_type, destroyed_count):
"""
Given a type and count of SAM units, determine if enough units were destroyed to warrant the
loss of a site
:param sam_type:
inidivudal unit name in SAM site which was destroyed
:param destroyed_count:
count of that unit type which was destroyed *in the sortie*
:return:
INT: number of sites lost
"""
sam_threshold = {
AirDefence.SAM_SR_P_19: 1,
AirDefence.SAM_SA_3_S_125_TR_SNR: 1,
AirDefence.SAM_SA_6_Kub_STR_9S91: 1,
AirDefence.SAM_SA_10_S_300PS_SR_5N66M: 1,
AirDefence.SAM_SA_10_S_300PS_TR_30N6: 1,
AirDefence.SAM_SA_10_S_300PS_CP_54K6: 1,
AirDefence.SAM_SA_10_S_300PS_SR_64H6E: 1,
AirDefence.SAM_SA_3_S_125_LN_5P73: 4,
AirDefence.SAM_SA_6_Kub_LN_2P25: 6,
AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 8,
AirDefence.SAM_SA_2_LN_SM_90:4,
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song: 1,
AirDefence.SAM_Hawk_PCP: 1,
AirDefence.SAM_Hawk_LN_M192: 4,
AirDefence.SAM_Hawk_SR_AN_MPQ_50: 1,
AirDefence.SAM_Hawk_TR_AN_MPQ_46: 1
}
return int(destroyed_count / sam_threshold[sam_type])
def determine_positions(position, heading, num_units, launcher_distance, coverage=90):
"""
Given a position on the map, array a group of units in a circle a uniform distance from the unit
:param position:
position of the center unit
:param heading:
the direction the units should be arranged toward if coverage is not 360
:param num_units:
number of units to play on the circle
:param launcher_distance:
distance the units should be from the center unit
:param coverage:
0-360
:return:
list of tuples representing each unit location
[(pos_x, pos_y, heading), ...]
"""
if coverage == 360:
# one of the positions is shared :'(
outer_offset = coverage / num_units
else:
outer_offset = coverage / (num_units - 1)
positions = []
if num_units % 2 == 0:
current_offset = heading - ((coverage / (num_units - 1)) / 2)
else:
current_offset = heading
current_offset -= outer_offset * (math.ceil(num_units / 2) - 1)
for x in range(1, num_units + 1):
positions.append((
position.x + launcher_distance * math.cos(math.radians(current_offset)),
position.y + launcher_distance * math.sin(math.radians(current_offset)),
current_offset,
))
current_offset += outer_offset
return positions
def aaa_vehicle_group(self, country, name, _type: unittype.VehicleType, position: mapping.Point,
heading=0, group_size=1,
formation=unitgroup.VehicleGroup.Formation.Line,
move_formation: PointAction=PointAction.OffRoad):
"""
Override the default vehicle group so that our group can contain a mix of units (which is required for advanced
SAM sites)
For further docstrings, see the built-in function
"""
vg = unitgroup.VehicleGroup(self.next_group_id(), self.string(name))
for i in range(1, group_size + 1):
heading = randint(0, 359)
if _type == AirDefence.SAM_SA_3_S_125_LN_5P73:
# 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR
num_launchers = 4
# search radar
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SR_P_19,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_3_S_125_TR_SNR,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=180,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_3_S_125_LN_5P73,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_6_Kub_LN_2P25:
# 6 launchers (360 degree coverage)
# 1 S/TR
# search/track radar
num_launchers = 6
v = self.vehicle(
name + " Unit #{nr}-str".format(nr=i),
AirDefence.SAM_SA_6_Kub_STR_9S91,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=360,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_6_Kub_LN_2P25,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_10_S_300PS_LN_5P85C:
# 8 launchers - 4 directions, two in each direction
# 1 SR (offset)
# 1 TR (center)
# search radar
num_launchers = 8
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_SR_5N66M,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_TR_30N6,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
# command center
v = self.vehicle(
name + " Unit #{nr}-c".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_CP_54K6,
)
center_x = position.x + randint(40, 60)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=150,
coverage=360,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_10_S_300PS_LN_5P85C,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_10_S_300PS_CP_54K6:
# 8 launchers - 4 directions, two in each direction
# 1 SR (offset)
# 1 TR (center)
# search radar
num_launchers = 8
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_SR_64H6E,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_TR_30N6,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
# command center
v = self.vehicle(
name + " Unit #{nr}-c".format(nr=i),
AirDefence.SAM_SA_10_S_300PS_CP_54K6,
)
center_x = position.x + randint(40, 60)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_units=num_launchers,
launcher_distance=150,
coverage=360,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_10_S_300PS_LN_5P85D,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_Hawk_PCP:
# 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR, 1 PCP
num_launchers = 4
# search radar
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_Hawk_SR_AN_MPQ_50,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_Hawk_TR_AN_MPQ_46,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
# PCP
v = self.vehicle(
name + " Unit #{nr}-pcp".format(nr=i),
AirDefence.SAM_Hawk_PCP,
)
center_x = position.x + randint(60, 80)
center_y = position.y + 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=180,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_Hawk_LN_M192,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
elif _type == AirDefence.SAM_SA_2_LN_SM_90:
# 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR
num_launchers = 4
# search radar
v = self.vehicle(
name + " Unit #{nr}-sr".format(nr=i),
AirDefence.SAM_SR_P_19,
)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
# track radar
v = self.vehicle(
name + " Unit #{nr}-tr".format(nr=i),
AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song,
)
center_x = position.x + randint(20, 40)
center_y = position.y + (i - 1) * 20
v.position.x = center_x
v.position.y = center_y
v.heading = heading
vg.add_unit(v)
plop_positions = determine_positions(
position,
heading,
num_launchers,
launcher_distance=100,
coverage=180,
)
for x in range(0, num_launchers):
v = self.vehicle(
name + " Unit #{nr}-{x}".format(nr=i, x=x),
AirDefence.SAM_SA_2_LN_SM_90,
)
v.position.x = plop_positions[x][0]
v.position.y = plop_positions[x][1]
v.heading = plop_positions[x][2]
vg.add_unit(v)
else:
v = self.vehicle(name + " Unit #{nr}-sam".format(nr=i), _type)
v.position.x = position.x
v.position.y = position.y + (i - 1) * 20
v.heading = heading
vg.add_unit(v)
wp = vg.add_waypoint(vg.units[0].position, move_formation, 0)
wp.ETA_locked = True
if _type.eplrs:
wp.tasks.append(task.EPLRS(self.next_eplrs("vehicle")))
country.add_vehicle_group(vg)
return vg
class AAConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict):
self.m = mission
self.conflict = conflict
def generate_at_defenders_location(self, units: db.AirDefenseDict):
for unit_type, count in units.items():
for _ in range(count):
self.m.vehicle_group(
country=self.conflict.defenders_country,
name=namegen.next_unit_name(self.conflict.defenders_country, unit_type),
_type=unit_type,
position=self.conflict.ground_defenders_location.random_point_within(100, 100),
group_size=1)
def generate(self, units: db.AirDefenseDict):
for type, count in units.items():
for _, radial in zip(range(count), self.conflict.radials):
distance = randint(self.conflict.size * DISTANCE_FACTOR[0] + 9000, self.conflict.size * DISTANCE_FACTOR[1] + 14000)
p = self.conflict.position.point_from_heading(random.choice(self.conflict.radials), distance)
self.m.aaa_vehicle_group(
country=self.conflict.defenders_country,
name=namegen.next_unit_name(self.conflict.defenders_country, type),
_type=type,
position=p,
group_size=1)
class ExtraAAConflictGenerator:
def __init__(self, mission: Mission, conflict: Conflict, game, player_country: Country, enemy_country: Country):
self.mission = mission
@@ -445,7 +21,6 @@ class ExtraAAConflictGenerator:
self.enemy_country = enemy_country
def generate(self):
from theater.conflicttheater import ControlPoint
for cp in self.game.theater.controlpoints:
if cp.is_global:

View File

@@ -242,11 +242,11 @@ class AircraftConflictGenerator:
else:
assert False
def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition, is_quick=False, should_orbit=False):
def _generate_escort(self, side: Country, units: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition, cp, is_quick=False, should_orbit=False):
groups = []
for flying_type, count, client_count in self._split_to_groups(units, clients):
group = self._generate_group(
name=namegen.next_unit_name(side, flying_type),
name=namegen.next_unit_name(side, cp.id, flying_type),
side=side,
unit_type=flying_type,
count=count,
@@ -279,7 +279,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@@ -313,7 +313,7 @@ class AircraftConflictGenerator:
try:
group = self._generate_at_airport(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@@ -322,7 +322,7 @@ class AircraftConflictGenerator:
start_type=StartType.Runway)
except Exception:
group = self._generate_group(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@@ -360,7 +360,7 @@ class AircraftConflictGenerator:
try:
group = self._generate_at_airport(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@@ -369,7 +369,7 @@ class AircraftConflictGenerator:
start_type=StartType.Runway)
except Exception:
group = self._generate_group(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@@ -413,7 +413,7 @@ class AircraftConflictGenerator:
try:
group = self._generate_at_airport(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@@ -422,7 +422,7 @@ class AircraftConflictGenerator:
start_type=StartType.Runway)
except Exception:
group = self._generate_group(
name=namegen.next_unit_name(country, type),
name=namegen.next_unit_name(country, cp.id, type),
side=country,
unit_type=type,
count=number,
@@ -450,7 +450,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@@ -476,7 +476,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@@ -502,7 +502,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.defenders_country, self.conflict.to_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@@ -528,7 +528,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@@ -552,6 +552,7 @@ class AircraftConflictGenerator:
clients=clients,
at=at and at or self._group_point(self.conflict.air_attackers_location),
is_quick=at is None,
cp=self.conflict.from_cp,
should_orbit=True):
self._rtb_for(g, self.conflict.from_cp, at)
@@ -562,13 +563,14 @@ class AircraftConflictGenerator:
clients=clients,
at=at and at or self._group_point(self.conflict.air_defenders_location),
is_quick=at is None,
cp=self.conflict.to_cp,
should_orbit=False):
self._rtb_for(g, self.conflict.to_cp, at)
def generate_defense(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.to_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@@ -585,7 +587,7 @@ class AircraftConflictGenerator:
def generate_migcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@@ -603,7 +605,7 @@ class AircraftConflictGenerator:
def generate_barcap(self, patrol: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(patrol, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@@ -629,7 +631,7 @@ class AircraftConflictGenerator:
for flying_type, count, client_count in self._split_to_groups(transport):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.defenders_country,
unit_type=flying_type,
count=count,
@@ -647,7 +649,7 @@ class AircraftConflictGenerator:
def generate_interception(self, interceptors: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
for flying_type, count, client_count in self._split_to_groups(interceptors, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, flying_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, flying_type),
side=self.conflict.attackers_country,
unit_type=flying_type,
count=count,
@@ -669,7 +671,7 @@ class AircraftConflictGenerator:
def generate_passenger_transport(self, helis: db.HeliDict, clients: db.HeliDict, at: db.StartingPosition):
for heli_type, count, client_count in self._split_to_groups(helis, clients):
group = self._generate_group(
name=namegen.next_unit_name(self.conflict.attackers_country, heli_type),
name=namegen.next_unit_name(self.conflict.attackers_country, self.conflict.from_cp.id, heli_type),
side=self.conflict.attackers_country,
unit_type=heli_type,
count=count,

View File

@@ -37,11 +37,17 @@ class ArmorConflictGenerator:
return point.random_point_within(distance, self.conflict.size * SPREAD_DISTANCE_SIZE_FACTOR)
def _generate_group(self, side: Country, unit: VehicleType, count: int, at: Point, to: Point = None, move_formation: PointAction = PointAction.OffRoad):
if side == self.conflict.attackers_country:
cp = self.conflict.from_cp
else:
cp = self.conflict.to_cp
for c in range(count):
logging.info("armorgen: {} for {}".format(unit, side.id))
group = self.m.vehicle_group(
side,
namegen.next_unit_name(side, unit),
namegen.next_unit_name(side, cp.id, unit),
unit,
position=self._group_point(at),
group_size=1,

View File

@@ -4,9 +4,9 @@ from game import db
class NameGenerator:
number = 0
def next_unit_name(self, country, unit_type):
def next_unit_name(self, country, parent_base_id, unit_type):
self.number += 1
return "unit|{}|{}|{}|".format(country.id, self.number, db.unit_type_name(unit_type))
return "unit|{}|{}|{}|{}|".format(country.id, self.number, parent_base_id, db.unit_type_name(unit_type))
def next_basedefense_name(self):
return "basedefense_aa|0|0|"