def redeploy_units(self, cp): """" Auto redeploy units to newly captured base """ ally_connected_cps = [ ocp for ocp in cp.connected_points if cp.captured == ocp.captured ] enemy_connected_cps = [ ocp for ocp in cp.connected_points if cp.captured != ocp.captured ] # If the newly captured cp does not have enemy connected cp, # then it is not necessary to redeploy frontline units there. if len(enemy_connected_cps) == 0: return else: # From each ally cp, send reinforcements for ally_cp in ally_connected_cps: total_units_redeployed = 0 own_enemy_cp = [ ocp for ocp in ally_cp.connected_points if ally_cp.captured != ocp.captured ] moved_units = {} # If the connected base, does not have any more enemy cp connected. # Or if it is not the opponent redeploying forces there (enemy AI will never redeploy all their forces at once) if len(own_enemy_cp) > 0 or not cp.captured: for frontline_unit, count in ally_cp.base.armor.items(): moved_units[frontline_unit] = int(count / 2) total_units_redeployed = total_units_redeployed + int( count / 2) else: # So if the old base, does not have any more enemy cp connected, or if it is an enemy base for frontline_unit, count in ally_cp.base.armor.items(): moved_units[frontline_unit] = count total_units_redeployed = total_units_redeployed + count cp.base.commision_units(moved_units) ally_cp.base.commit_losses(moved_units) if total_units_redeployed > 0: info = Information("Units redeployed", "", self.game.turn) info.text = str( total_units_redeployed ) + " units have been redeployed from " + ally_cp.name + " to " + cp.name self.game.informations.append(info) logging.info(info.text)
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)