def get_carrier_group_name(self): """ Get the carrier group name if the airbase is a carrier :return: Carrier group name """ if self.cptype in [ ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP ]: for g in self.ground_objects: if g.dcs_identifier == "CARRIER": for group in g.groups: for u in group.units: if db.unit_type_from_name(u.type) in [ CVN_74_John_C__Stennis, CV_1143_5_Admiral_Kuznetsov ]: return group.name elif g.dcs_identifier == "LHA": for group in g.groups: for u in group.units: if db.unit_type_from_name( u.type) in [LHA_1_Tarawa]: return group.name return None
def generate(self) -> None: if self.game.position_culled(self.ground_object.position): return for group in self.ground_object.groups: if not group.units: logging.warning(f"Found empty group in {self.ground_object}") continue unit_type = unit_type_from_name(group.units[0].type) if unit_type is None: raise RuntimeError( f"Unrecognized unit type: {group.units[0].type}") vg = self.m.vehicle_group(self.country, group.name, unit_type, position=group.position, heading=group.units[0].heading) vg.units[0].name = self.m.string(group.units[0].name) vg.units[0].player_can_drive = True for i, u in enumerate(group.units): if i > 0: vehicle = Vehicle(self.m.next_unit_id(), self.m.string(u.name), u.type) vehicle.position.x = u.position.x vehicle.position.y = u.position.y vehicle.heading = u.heading vehicle.player_can_drive = True vg.add_unit(vehicle) self.enable_eplrs(vg, unit_type) self.set_alarm_state(vg)
def object_has_radar(ground_object: TheaterGroundObject) -> bool: """Returns True if the ground object contains a unit with radar.""" for group in ground_object.groups: for unit in group.units: if db.unit_type_from_name(unit.type) in UNITS_WITH_RADAR: return True return False
def create_ship(self, unit: Unit, atc_channel: RadioFrequency) -> Ship: ship = Ship(self.m.next_unit_id(), self.m.string(unit.name), unit_type_from_name(unit.type)) ship.position.x = unit.position.x ship.position.y = unit.position.y ship.heading = unit.heading # TODO: Verify. ship.set_frequency(atc_channel.hertz) return ship
def runway_is_operational(self) -> bool: # Necessary because it's possible for the carrier itself to have sunk # while its escorts are still alive. for g in self.ground_objects: if g.dcs_identifier in ["CARRIER", "LHA"]: for group in g.groups: for u in group.units: if db.unit_type_from_name(u.type) in [ CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov, Type_071_Amphibious_Transport_Dock]: return True return False
def runway_is_operational(self) -> bool: # Necessary because it's possible for the carrier itself to have sunk # while its escorts are still alive. for group in self.find_main_tgo().groups: for u in group.units: if db.unit_type_from_name(u.type) in [ Stennis, LHA_Tarawa, KUZNECOW, Type_071, ]: return True return False
def generate(self) -> None: if self.game.position_culled(self.ground_object.position): return for group in self.ground_object.groups: if not group.units: logging.warning(f"Found empty group in {self.ground_object}") continue unit_type = unit_type_from_name(group.units[0].type) if unit_type is None: raise RuntimeError(f"Unrecognized unit type: {group.units[0].type}") self.generate_group(group, unit_type)
def get_carrier_group_name(self) -> Optional[str]: """ Get the carrier group name if the airbase is a carrier :return: Carrier group name """ if self.cptype in [ ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP, ]: for g in self.ground_objects: if g.dcs_identifier == "CARRIER": for group in g.groups: for u in group.units: if db.unit_type_from_name(u.type) in [ Stennis, KUZNECOW, ]: return group.name elif g.dcs_identifier == "LHA": for group in g.groups: for u in group.units: if db.unit_type_from_name(u.type) in [LHA_Tarawa]: return group.name return None
def add_front_line_units(self, group: Group, origin: ControlPoint) -> None: for unit in group.units: # The actual name is a String (the pydcs translatable string), which # doesn't define __eq__. name = str(unit.name) if name in self.front_line_units: raise RuntimeError(f"Duplicate front line unit: {name}") unit_type = db.unit_type_from_name(unit.type) if unit_type is None: raise RuntimeError(f"Unknown unit type: {unit.type}") if not issubclass(unit_type, VehicleType): raise RuntimeError( f"{name} is a {unit_type.__name__}, expected a VehicleType" ) self.front_line_units[name] = FrontLineUnit(unit_type, origin)
def has_runway(self): """ Check whether this control point can have aircraft taking off or landing. :return: """ if self.cptype in [ControlPointType.AIRCRAFT_CARRIER_GROUP, ControlPointType.LHA_GROUP] : for g in self.ground_objects: if g.dcs_identifier in ["CARRIER", "LHA"]: for group in g.groups: for u in group.units: if db.unit_type_from_name(u.type) in [CVN_74_John_C__Stennis, LHA_1_Tarawa, CV_1143_5_Admiral_Kuznetsov]: return True return False elif self.cptype in [ControlPointType.AIRBASE, ControlPointType.FARP]: return True else: return True
def generate_group(self, group_def: Group, unit_type: UnitType): group = self.m.ship_group(self.country, group_def.name, unit_type, position=group_def.position, heading=group_def.units[0].heading) group.units[0].name = self.m.string(group_def.units[0].name) # TODO: Skipping the first unit looks like copy pasta from the carrier. for unit in group_def.units[1:]: unit_type = unit_type_from_name(unit.type) ship = Ship(self.m.next_unit_id(), self.m.string(unit.name), unit_type) ship.position.x = unit.position.x ship.position.y = unit.position.y ship.heading = unit.heading group.add_unit(ship) self.set_alarm_state(group)
def compute_sead_targets(self): """ @return a list of potential sead targets in range """ # target, distance self.potential_sead_targets = [] for cp in [ c for c in self.game.theater.controlpoints if c.captured != self.from_cp.captured ]: # Compute distance to current cp distance = math.hypot(cp.position.x - self.from_cp.position.x, cp.position.y - self.from_cp.position.y) # Then it's unlikely any ground object is range if distance > 2 * self.doctrine["SEAD_MAX_RANGE"]: return for g in cp.ground_objects: if g.dcs_identifier == "AA": # Check that there is at least one unit with a radar in the ground objects unit groups number_of_units = sum([ len([ r for r in group.units if db.unit_type_from_name( r.type) in UNITS_WITH_RADAR ]) for group in g.groups ]) if number_of_units <= 0: continue # Compute distance to current cp distance = math.hypot( cp.position.x - self.from_cp.position.x, cp.position.y - self.from_cp.position.y) if distance < self.doctrine["SEAD_MAX_RANGE"]: self.potential_sead_targets.append((g, distance)) self.potential_sead_targets.sort(key=operator.itemgetter(1))
def generate_group(self, group_def: ShipGroup, first_unit_type: Type[ShipType]) -> None: group = self.m.ship_group( self.country, group_def.name, first_unit_type, position=group_def.position, heading=group_def.units[0].heading, ) group.units[0].name = group_def.units[0].name # TODO: Skipping the first unit looks like copy pasta from the carrier. for unit in group_def.units[1:]: unit_type = unit_type_from_name(unit.type) ship = Ship(self.m.next_unit_id(), unit.name, unit_type) ship.position.x = unit.position.x ship.position.y = unit.position.y ship.heading = unit.heading group.add_unit(ship) self.set_alarm_state(group) self._register_unit_group(group_def, group)
def aa_ranges(ground_object: TheaterGroundObject) -> Tuple[int, int]: detection_range = 0 threat_range = 0 for g in ground_object.groups: for u in g.units: unit = db.unit_type_from_name(u.type) if unit is None: logging.error(f"Unknown unit type {u.type}") continue # Some units in pydcs have detection_range and threat_range # defined, but explicitly set to None. unit_detection_range = getattr(unit, "detection_range", None) if unit_detection_range is not None: detection_range = max(detection_range, unit_detection_range) unit_threat_range = getattr(unit, "threat_range", None) if unit_threat_range is not None: threat_range = max(threat_range, unit_threat_range) return detection_range, threat_range
def generate(self): for cp in self.game.theater.controlpoints: if cp.captured: country = self.game.player_country else: country = self.game.enemy_country side = self.m.country(country) for ground_object in cp.ground_objects: if ground_object.dcs_identifier == "AA": if self.game.position_culled(ground_object.position): continue for g in ground_object.groups: if len(g.units) > 0: utype = unit_type_from_name(g.units[0].type) if not ground_object.sea_object: vg = self.m.vehicle_group( side, g.name, utype, position=g.position, heading=g.units[0].heading) vg.units[0].name = self.m.string( g.units[0].name) vg.units[0].player_can_drive = True for i, u in enumerate(g.units): if i > 0: vehicle = Vehicle( self.m.next_unit_id(), self.m.string(u.name), u.type) vehicle.position.x = u.position.x vehicle.position.y = u.position.y vehicle.heading = u.heading vehicle.player_can_drive = True vg.add_unit(vehicle) if hasattr(utype, 'eplrs'): if utype.eplrs: vg.points[0].tasks.append(EPLRS(vg.id)) else: vg = self.m.ship_group( side, g.name, utype, position=g.position, heading=g.units[0].heading) vg.units[0].name = self.m.string( g.units[0].name) for i, u in enumerate(g.units): utype = unit_type_from_name(u.type) if i > 0: ship = Ship(self.m.next_unit_id(), self.m.string(u.name), utype) ship.position.x = u.position.x ship.position.y = u.position.y ship.heading = u.heading vg.add_unit(ship) if self.game.settings.perf_red_alert_state: vg.points[0].tasks.append(OptAlarmState(2)) else: vg.points[0].tasks.append(OptAlarmState(1)) elif ground_object.dcs_identifier in ["CARRIER", "LHA"]: for g in ground_object.groups: if len(g.units) > 0: utype = unit_type_from_name(g.units[0].type) if ground_object.dcs_identifier == "CARRIER" and self.game.settings.supercarrier == True: utype = db.upgrade_to_supercarrier( utype, cp.name) sg = self.m.ship_group(side, g.name, utype, position=g.position, heading=g.units[0].heading) atc_channel = self.radio_registry.alloc_uhf() sg.set_frequency(atc_channel.hertz) sg.units[0].name = self.m.string(g.units[0].name) for i, u in enumerate(g.units): if i > 0: ship = Ship(self.m.next_unit_id(), self.m.string(u.name), unit_type_from_name(u.type)) ship.position.x = u.position.x ship.position.y = u.position.y ship.heading = u.heading # TODO: Verify. ship.set_frequency(atc_channel.hertz) sg.add_unit(ship) # Find carrier direction (In the wind) found_carrier_destination = False attempt = 0 while not found_carrier_destination and attempt < 5: point = sg.points[ 0].position.point_from_heading( self.m.weather.wind_at_ground.direction + 180, 100000 - attempt * 20000) if self.game.theater.is_in_sea(point): found_carrier_destination = True sg.add_waypoint(point) else: attempt = attempt + 1 # Set UP TACAN and ICLS tacan = self.tacan_registry.alloc_for_band( TacanBand.X) icls_channel = next(self.icls_alloc) # TODO: Assign these properly. if ground_object.dcs_identifier == "CARRIER": tacan_callsign = random.choice([ "STE", "CVN", "CVH", "CCV", "ACC", "ARC", "GER", "ABR", "LIN", "TRU", ]) else: tacan_callsign = random.choice([ "LHD", "LHA", "LHB", "LHC", "LHD", "LDS", ]) sg.points[0].tasks.append( ActivateBeaconCommand( channel=tacan.number, modechannel=tacan.band.value, callsign=tacan_callsign, unit_id=sg.units[0].id, aa=False)) sg.points[0].tasks.append( ActivateICLSCommand(icls_channel, unit_id=sg.units[0].id)) # TODO: Make unit name usable. # This relies on one control point mapping exactly # to one LHA, carrier, or other usable "runway". # This isn't wholly true, since the DD escorts of # the carrier group are valid for helicopters, but # they aren't exposed as such to the game. Should # clean this up so that's possible. We can't use the # unit name since it's an arbitrary ID. self.runways[cp.name] = RunwayData( cp.name, "N/A", atc=atc_channel, tacan=tacan, tacan_callsign=tacan_callsign, icls=icls_channel, ) else: if self.game.position_culled(ground_object.position): continue static_type = None if ground_object.dcs_identifier in warehouse_map: static_type = warehouse_map[ ground_object.dcs_identifier] elif ground_object.dcs_identifier in fortification_map: static_type = fortification_map[ ground_object.dcs_identifier] elif ground_object.dcs_identifier in FORTIFICATION_UNITS_ID: for f in FORTIFICATION_UNITS: if f.id == ground_object.dcs_identifier: unit_type = f break else: print("Didn't find {} in static _map(s)!".format( ground_object.dcs_identifier)) continue if static_type is None: if not ground_object.is_dead: group = self.m.vehicle_group( country=side, name=ground_object.string_identifier, _type=unit_type, position=ground_object.position, heading=ground_object.heading, ) logging.info( "generated {}object identifier {} with mission id {}" .format( "dead " if ground_object.is_dead else "", group.name, group.id)) else: group = self.m.static_group( country=side, name=ground_object.string_identifier, _type=static_type, position=ground_object.position, heading=ground_object.heading, dead=ground_object.is_dead, ) logging.info( "generated {}object identifier {} with mission id {}" .format("dead " if ground_object.is_dead else "", group.name, group.id))
def __init__(self, state_data, game): self.base_capture_events = state_data["base_capture_events"] self.killed_aircrafts = state_data["killed_aircrafts"] self.killed_ground_units = state_data["killed_ground_units"] self.weapons_fired = state_data["weapons_fired"] self.mission_ended = state_data["mission_ended"] logging.info("--------------------------------") logging.info("Starting Debriefing preprocessing") logging.info("--------------------------------") logging.info(self.base_capture_events) logging.info(self.killed_aircrafts) logging.info(self.killed_ground_units) logging.info(self.weapons_fired) logging.info(self.mission_ended) logging.info("--------------------------------") self.player_country_id = db.country_id_from_name(game.player_country) self.enemy_country_id = db.country_id_from_name(game.enemy_country) self.dead_aircraft = [] self.dead_units = [] self.dead_aaa_groups = [] self.dead_buildings = [] for aircraft in self.killed_aircrafts: try: country = int(aircraft.split("|")[1]) type = db.unit_type_from_name(aircraft.split("|")[4]) player_unit = (country == self.player_country_id) aircraft = DebriefingDeadUnitInfo(country, player_unit, type) if type is not None: self.dead_aircraft.append(aircraft) except Exception as e: logging.error(e) for unit in self.killed_ground_units: try: country = int(unit.split("|")[1]) type = db.unit_type_from_name(unit.split("|")[4]) player_unit = (country == self.player_country_id) unit = DebriefingDeadUnitInfo(country, player_unit, type) if type is not None: self.dead_units.append(unit) except Exception as e: logging.error(e) for unit in self.killed_ground_units: for cp in game.theater.controlpoints: logging.info(cp.name) logging.info(cp.captured) if cp.captured: country = self.player_country_id else: country = self.enemy_country_id player_unit = (country == self.player_country_id) for i, ground_object in enumerate(cp.ground_objects): logging.info(unit) logging.info(ground_object.string_identifier) if ground_object.matches_string_identifier(unit): unit = DebriefingDeadUnitInfo(country, player_unit, ground_object.dcs_identifier) self.dead_buildings.append(unit) elif ground_object.dcs_identifier in ["AA", "CARRIER", "LHA"]: for g in ground_object.groups: for u in g.units: if u.name == unit: unit = DebriefingDeadUnitInfo(country, player_unit, db.unit_type_from_name(u.type)) self.dead_units.append(unit) self.player_dead_aircraft = [a for a in self.dead_aircraft if a.country_id == self.player_country_id] self.enemy_dead_aircraft = [a for a in self.dead_aircraft if a.country_id == self.enemy_country_id] self.player_dead_units = [a for a in self.dead_units if a.country_id == self.player_country_id] self.enemy_dead_units = [a for a in self.dead_units if a.country_id == self.enemy_country_id] self.player_dead_buildings = [a for a in self.dead_buildings if a.country_id == self.player_country_id] self.enemy_dead_buildings = [a for a in self.dead_buildings if a.country_id == self.enemy_country_id] logging.info(self.player_dead_aircraft) logging.info(self.enemy_dead_aircraft) logging.info(self.player_dead_units) logging.info(self.enemy_dead_units) self.player_dead_aircraft_dict = {} for a in self.player_dead_aircraft: if a.type in self.player_dead_aircraft_dict.keys(): self.player_dead_aircraft_dict[a.type] = self.player_dead_aircraft_dict[a.type] + 1 else: self.player_dead_aircraft_dict[a.type] = 1 self.enemy_dead_aircraft_dict = {} for a in self.enemy_dead_aircraft: if a.type in self.enemy_dead_aircraft_dict.keys(): self.enemy_dead_aircraft_dict[a.type] = self.enemy_dead_aircraft_dict[a.type] + 1 else: self.enemy_dead_aircraft_dict[a.type] = 1 self.player_dead_units_dict = {} for a in self.player_dead_units: if a.type in self.player_dead_units_dict.keys(): self.player_dead_units_dict[a.type] = self.player_dead_units_dict[a.type] + 1 else: self.player_dead_units_dict[a.type] = 1 self.enemy_dead_units_dict = {} for a in self.enemy_dead_units: if a.type in self.enemy_dead_units_dict.keys(): self.enemy_dead_units_dict[a.type] = self.enemy_dead_units_dict[a.type] + 1 else: self.enemy_dead_units_dict[a.type] = 1 self.player_dead_buildings_dict = {} for a in self.player_dead_buildings: if a.type in self.player_dead_buildings_dict.keys(): self.player_dead_buildings_dict[a.type] = self.player_dead_buildings_dict[a.type] + 1 else: self.player_dead_buildings_dict[a.type] = 1 self.enemy_dead_buildings_dict = {} for a in self.enemy_dead_buildings: if a.type in self.enemy_dead_buildings_dict.keys(): self.enemy_dead_buildings_dict[a.type] = self.enemy_dead_buildings_dict[a.type] + 1 else: self.enemy_dead_buildings_dict[a.type] = 1 logging.info("--------------------------------") logging.info("Debriefing pre process results :") logging.info("--------------------------------") logging.info(self.player_dead_aircraft_dict) logging.info(self.enemy_dead_aircraft_dict) logging.info(self.player_dead_units_dict) logging.info(self.enemy_dead_units_dict) logging.info(self.player_dead_buildings_dict) logging.info(self.enemy_dead_buildings_dict)
def commit(self, debriefing: Debriefing): logging.info("Commiting mission results") # ------------------------------ # Destroyed aircrafts cp_map = {cp.id: cp for cp in self.game.theater.controlpoints} for destroyed_aircraft in debriefing.killed_aircrafts: try: cpid = int(destroyed_aircraft.split("|")[3]) type = db.unit_type_from_name(destroyed_aircraft.split("|")[4]) if cpid in cp_map.keys(): cp = cp_map[cpid] if type in cp.base.aircraft.keys(): logging.info("Aircraft destroyed : " + str(type)) cp.base.aircraft[type] = max( 0, cp.base.aircraft[type] - 1) except Exception as e: print(e) # ------------------------------ # Destroyed ground units killed_unit_count_by_cp = { cp.id: 0 for cp in self.game.theater.controlpoints } cp_map = {cp.id: cp for cp in self.game.theater.controlpoints} for killed_ground_unit in debriefing.killed_ground_units: try: cpid = int(killed_ground_unit.split("|")[3]) type = db.unit_type_from_name(killed_ground_unit.split("|")[4]) if cpid in cp_map.keys(): killed_unit_count_by_cp[ cpid] = killed_unit_count_by_cp[cpid] + 1 cp = cp_map[cpid] if type in cp.base.armor.keys(): logging.info("Ground unit destroyed : " + str(type)) cp.base.armor[type] = max(0, cp.base.armor[type] - 1) except Exception as e: print(e) # ------------------------------ # Static ground objects for destroyed_ground_unit_name in debriefing.killed_ground_units: for cp in self.game.theater.controlpoints: if not cp.ground_objects: continue # -- Static ground objects for i, ground_object in enumerate(cp.ground_objects): if ground_object.is_dead: continue if ground_object.matches_string_identifier( destroyed_ground_unit_name): logging.info("cp {} killing ground object {}".format( cp, ground_object.string_identifier)) cp.ground_objects[i].is_dead = True info = Information( "Building destroyed", ground_object.dcs_identifier + " has been destroyed at location " + ground_object.obj_name, self.game.turn) self.game.informations.append(info) # -- AA Site groups destroyed_units = 0 info = Information( "Units destroyed at " + ground_object.obj_name, "", self.game.turn) for i, ground_object in enumerate(cp.ground_objects): if ground_object.dcs_identifier in [ "AA", "CARRIER", "LHA" ]: for g in ground_object.groups: if not hasattr(g, "units_losts"): g.units_losts = [] for u in g.units: if u.name == destroyed_ground_unit_name: g.units.remove(u) g.units_losts.append(u) destroyed_units = destroyed_units + 1 info.text = u.type ucount = sum( [len(g.units) for g in ground_object.groups]) if ucount == 0: ground_object.is_dead = True if destroyed_units > 0: self.game.informations.append(info) # ------------------------------ # Captured bases #if self.game.player_country in db.BLUEFOR_FACTIONS: coalition = 2 # Value in DCS mission event for BLUE #else: # coalition = 1 # Value in DCS mission event for RED for captured in debriefing.base_capture_events: try: id = int(captured.split("||")[0]) new_owner_coalition = int(captured.split("||")[1]) captured_cps = [] for cp in self.game.theater.controlpoints: if cp.id == id: if cp.captured and new_owner_coalition != coalition: cp.captured = False info = Information( cp.name + " lost !", "The ennemy took control of " + cp.name + "\nShame on us !", self.game.turn) self.game.informations.append(info) pname = self.game.enemy_name captured_cps.append(cp) elif not (cp.captured ) and new_owner_coalition == coalition: cp.captured = True info = Information( cp.name + " captured !", "We took control of " + cp.name + "! Great job !", self.game.turn) self.game.informations.append(info) pname = self.game.player_name captured_cps.append(cp) else: continue cp.base.aircraft = {} cp.base.armor = {} airbase_def_id = 0 for g in cp.ground_objects: g.groups = [] if g.airbase_group and pname != "": generate_airbase_defense_group( airbase_def_id, g, pname, self.game, cp) airbase_def_id = airbase_def_id + 1 for cp in captured_cps: logging.info("Will run redeploy for " + cp.name) self.redeploy_units(cp) except Exception as e: print(e) # Destroyed units carcass # ------------------------- for destroyed_unit in debriefing.destroyed_units: self.game.add_destroyed_units(destroyed_unit) # ----------------------------------- # Compute damage to bases for cp in self.game.theater.player_points(): enemy_cps = [e for e in cp.connected_points if not e.captured] for enemy_cp in enemy_cps: print("Compute frontline progression for : " + cp.name + " to " + enemy_cp.name) delta = 0 player_won = True ally_casualties = killed_unit_count_by_cp[cp.id] enemy_casualties = killed_unit_count_by_cp[enemy_cp.id] ally_units_alive = cp.base.total_armor enemy_units_alive = enemy_cp.base.total_armor print(ally_units_alive) print(enemy_units_alive) print(ally_casualties) print(enemy_casualties) ratio = (1.0 + enemy_casualties) / (1.0 + ally_casualties) player_aggresive = cp.stances[enemy_cp.id] in [ CombatStance.AGGRESIVE, CombatStance.ELIMINATION, CombatStance.BREAKTHROUGH ] if ally_units_alive == 0: player_won = False delta = STRONG_DEFEAT_INFLUENCE elif enemy_units_alive == 0: player_won = True delta = STRONG_DEFEAT_INFLUENCE elif cp.stances[enemy_cp.id] == CombatStance.RETREAT: player_won = False delta = STRONG_DEFEAT_INFLUENCE else: if enemy_casualties > ally_casualties: player_won = True if cp.stances[ enemy_cp.id] == CombatStance.BREAKTHROUGH: delta = STRONG_DEFEAT_INFLUENCE else: if ratio > 3: delta = STRONG_DEFEAT_INFLUENCE elif ratio < 1.5: delta = MINOR_DEFEAT_INFLUENCE else: delta = DEFEAT_INFLUENCE elif ally_casualties > enemy_casualties: if ally_units_alive > 2 * enemy_units_alive and player_aggresive: # Even with casualties if the enemy is overwhelmed, they are going to lose ground player_won = True delta = MINOR_DEFEAT_INFLUENCE elif ally_units_alive > 3 * enemy_units_alive and player_aggresive: player_won = True delta = STRONG_DEFEAT_INFLUENCE else: # But is the enemy is not outnumbered, we lose player_won = False if cp.stances[ enemy_cp.id] == CombatStance.BREAKTHROUGH: delta = STRONG_DEFEAT_INFLUENCE else: delta = STRONG_DEFEAT_INFLUENCE # No progress with defensive strategies if player_won and cp.stances[enemy_cp.id] in [ CombatStance.DEFENSIVE, CombatStance.AMBUSH ]: print("Defensive stance, progress is limited") delta = MINOR_DEFEAT_INFLUENCE if player_won: print(cp.name + " won ! factor > " + str(delta)) cp.base.affect_strength(delta) enemy_cp.base.affect_strength(-delta) info = Information( "Frontline Report", "Our ground forces from " + cp.name + " are making progress toward " + enemy_cp.name, self.game.turn) self.game.informations.append(info) else: print(cp.name + " lost ! factor > " + str(delta)) enemy_cp.base.affect_strength(delta) cp.base.affect_strength(-delta) info = Information( "Frontline Report", "Our ground forces from " + cp.name + " are losing ground against the enemy forces from " + enemy_cp.name, self.game.turn) self.game.informations.append(info)
def generate(self): cp = None # type: ControlPoint if self.conflict.attackers_country.name == self.game.player_country: cp = self.conflict.to_cp else: cp = self.conflict.from_cp for cp in self.game.theater.controlpoints: if cp.captured: country = self.game.player_country else: country = self.game.enemy_country side = self.m.country(country) for ground_object in cp.ground_objects: if ground_object.dcs_identifier == "AA": if self.game.position_culled(ground_object.position): continue for g in ground_object.groups: if len(g.units) > 0: utype = unit_type_from_name(g.units[0].type) if not ground_object.sea_object: vg = self.m.vehicle_group( side, g.name, utype, position=g.position, heading=g.units[0].heading) vg.units[0].name = self.m.string( g.units[0].name) for i, u in enumerate(g.units): if i > 0: vehicle = Vehicle( self.m.next_unit_id(), self.m.string(u.name), u.type) vehicle.position.x = u.position.x vehicle.position.y = u.position.y vehicle.heading = u.heading vg.add_unit(vehicle) else: vg = self.m.ship_group( side, g.name, utype, position=g.position, heading=g.units[0].heading) vg.units[0].name = self.m.string( g.units[0].name) for i, u in enumerate(g.units): utype = unit_type_from_name(u.type) if i > 0: ship = Ship(self.m.next_unit_id(), self.m.string(u.name), utype) ship.position.x = u.position.x ship.position.y = u.position.y ship.heading = u.heading vg.add_unit(ship) if self.game.settings.perf_red_alert_state: vg.points[0].tasks.append(OptAlarmState(2)) else: vg.points[0].tasks.append(OptAlarmState(1)) elif ground_object.dcs_identifier in ["CARRIER", "LHA"]: for g in ground_object.groups: if len(g.units) > 0: utype = unit_type_from_name(g.units[0].type) if ground_object.dcs_identifier == "CARRIER" and self.game.settings.supercarrier == True: utype = db.upgrade_to_supercarrier( utype, cp.name) sg = self.m.ship_group(side, g.name, utype, position=g.position, heading=g.units[0].heading) sg.units[0].name = self.m.string(g.units[0].name) for i, u in enumerate(g.units): if i > 0: ship = Ship(self.m.next_unit_id(), self.m.string(u.name), unit_type_from_name(u.type)) ship.position.x = u.position.x ship.position.y = u.position.y ship.heading = u.heading sg.add_unit(ship) # Find carrier direction (In the wind) found_carrier_destination = False attempt = 0 while not found_carrier_destination and attempt < 5: point = sg.points[ 0].position.point_from_heading( self.m.weather.wind_at_ground. direction, 100000 - attempt * 20000) if self.game.theater.is_in_sea(point): found_carrier_destination = True sg.add_waypoint(point) else: attempt = attempt + 1 # Set UP TACAN and ICLS modeChannel = "X" if not cp.tacanY else "Y" sg.points[0].tasks.append( ActivateBeaconCommand(channel=cp.tacanN, modechannel=modeChannel, callsign=cp.tacanI, unit_id=sg.units[0].id)) if ground_object.dcs_identifier == "CARRIER" and hasattr( cp, "icls"): sg.points[0].tasks.append( ActivateICLSCommand( cp.icls, unit_id=sg.units[0].id)) else: if self.game.position_culled(ground_object.position): continue static_type = None if ground_object.dcs_identifier in warehouse_map: static_type = warehouse_map[ ground_object.dcs_identifier] elif ground_object.dcs_identifier in fortification_map: static_type = fortification_map[ ground_object.dcs_identifier] elif ground_object.dcs_identifier in FORTIFICATION_UNITS_ID: for f in FORTIFICATION_UNITS: if f.id == ground_object.dcs_identifier: unit_type = f break else: print("Didn't find {} in static _map(s)!".format( ground_object.dcs_identifier)) continue if static_type is None: if not ground_object.is_dead: group = self.m.vehicle_group( country=side, name=ground_object.string_identifier, _type=unit_type, position=ground_object.position, heading=ground_object.heading, ) logging.info( "generated {}object identifier {} with mission id {}" .format( "dead " if ground_object.is_dead else "", group.name, group.id)) else: group = self.m.static_group( country=side, name=ground_object.string_identifier, _type=static_type, position=ground_object.position, heading=ground_object.heading, dead=ground_object.is_dead, ) logging.info( "generated {}object identifier {} with mission id {}" .format("dead " if ground_object.is_dead else "", group.name, group.id))
def reload_scene(self): scene = self.scene() scene.clear() playerColor = self.game.get_player_color() enemyColor = self.game.get_enemy_color() self.addBackground() # Uncomment below to help set up theater reference points #for i, r in enumerate(self.game.theater.reference_points.items()): # text = scene.addText(str(r), font=QFont("Trebuchet MS", 10, weight=5, italic=False)) # text.setPos(0, i * 24) for cp in self.game.theater.controlpoints: pos = self._transform_point(cp.position) scene.addItem(QMapControlPoint(self, pos[0] - CONST.CP_SIZE / 2, pos[1] - CONST.CP_SIZE / 2, CONST.CP_SIZE, CONST.CP_SIZE, cp, self.game)) if cp.captured: pen = QPen(brush=CONST.COLORS[playerColor]) brush = CONST.COLORS[playerColor+"_transparent"] else: pen = QPen(brush=CONST.COLORS[enemyColor]) brush = CONST.COLORS[enemyColor+"_transparent"] added_objects = [] for ground_object in cp.ground_objects: if ground_object.obj_name in added_objects: continue go_pos = self._transform_point(ground_object.position) if not ground_object.airbase_group: buildings = self.game.theater.find_ground_objects_by_obj_name(ground_object.obj_name) scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 12, 12, cp, ground_object, buildings)) if ground_object.category == "aa" and self.get_display_rule("sam"): max_range = 0 has_radar = False if ground_object.groups: for g in ground_object.groups: for u in g.units: unit = db.unit_type_from_name(u.type) if unit in UNITS_WITH_RADAR: has_radar = True if unit.threat_range > max_range: max_range = unit.threat_range if has_radar: scene.addEllipse(go_pos[0] - max_range/300.0 + 8, go_pos[1] - max_range/300.0 + 8, max_range/150.0, max_range/150.0, CONST.COLORS["white_transparent"], CONST.COLORS["grey_transparent"]) added_objects.append(ground_object.obj_name) for cp in self.game.theater.enemy_points(): if self.get_display_rule("lines"): self.scene_create_lines_for_cp(cp, playerColor, enemyColor) for cp in self.game.theater.player_points(): if self.get_display_rule("lines"): self.scene_create_lines_for_cp(cp, playerColor, enemyColor) for cp in self.game.theater.controlpoints: if cp.captured: pen = QPen(brush=CONST.COLORS[playerColor]) brush = CONST.COLORS[playerColor+"_transparent"] flight_path_pen = QPen(brush=CONST.COLORS[playerColor]) flight_path_pen.setColor(CONST.COLORS[playerColor]) else: pen = QPen(brush=CONST.COLORS[enemyColor]) brush = CONST.COLORS[enemyColor+"_transparent"] flight_path_pen = QPen(brush=CONST.COLORS[enemyColor]) flight_path_pen.setColor(CONST.COLORS[enemyColor]) flight_path_pen.setWidth(1) flight_path_pen.setStyle(Qt.DashDotLine) pos = self._transform_point(cp.position) if self.get_display_rule("flight_paths"): if cp.id in self.game.planners.keys(): planner = self.game.planners[cp.id] for flight in planner.flights: scene.addEllipse(pos[0], pos[1], 4, 4) prev_pos = list(pos) for point in flight.points: new_pos = self._transform_point(Point(point.x, point.y)) scene.addLine(prev_pos[0]+2, prev_pos[1]+2, new_pos[0]+2, new_pos[1]+2, flight_path_pen) scene.addEllipse(new_pos[0], new_pos[1], 4, 4, pen, brush) prev_pos = list(new_pos) scene.addLine(prev_pos[0] + 2, prev_pos[1] + 2, pos[0] + 2, pos[1] + 2, flight_path_pen) for cp in self.game.theater.controlpoints: pos = self._transform_point(cp.position) text = scene.addText(cp.name, font=CONST.FONT_MAP) text.setPos(pos[0] + CONST.CP_SIZE, pos[1] - CONST.CP_SIZE / 2) text = scene.addText(cp.name, font=CONST.FONT_MAP) text.setDefaultTextColor(Qt.white) text.setPos(pos[0] + CONST.CP_SIZE + 1, pos[1] - CONST.CP_SIZE / 2 + 1)
def get_carrier_type(self, group: Group) -> UnitType: unit_type = unit_type_from_name(group.units[0].type) if unit_type is None: raise RuntimeError( f"Unrecognized carrier name: {group.units[0].type}") return unit_type