def evaluate_invasion_planet(planet_id, empire, secure_fleet_missions, verbose=True): """Return the invasion value (score, troops) of a planet.""" detail = [] building_values = {"BLD_IMPERIAL_PALACE": 1000, "BLD_CULTURE_ARCHIVES": 1000, "BLD_SHIPYARD_BASE": 100, "BLD_SHIPYARD_ORG_ORB_INC": 200, "BLD_SHIPYARD_ORG_XENO_FAC": 200, "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200, "BLD_SHIPYARD_CON_NANOROBO": 300, "BLD_SHIPYARD_CON_GEOINT": 400, "BLD_SHIPYARD_CON_ADV_ENGINE": 1000, "BLD_SHIPYARD_AST": 300, "BLD_SHIPYARD_AST_REF": 1000, "BLD_SHIPYARD_ENRG_SOLAR": 1500, "BLD_INDUSTRY_CENTER": 500, "BLD_GAS_GIANT_GEN": 200, "BLD_SOL_ORB_GEN": 800, "BLD_BLACK_HOLE_POW_GEN": 2000, "BLD_ENCLAVE_VOID": 500, "BLD_NEUTRONIUM_EXTRACTOR": 2000, "BLD_NEUTRONIUM_SYNTH": 2000, "BLD_NEUTRONIUM_FORGE": 1000, "BLD_CONC_CAMP": 100, "BLD_BIOTERROR_PROJECTOR": 1000, "BLD_SHIPYARD_ENRG_COMP": 3000, } # TODO: add more factors, as used for colonization universe = fo.getUniverse() empire_id = empire.empireID max_jumps = 8 planet = universe.getPlanet(planet_id) if planet is None: # TODO: exclude planets with stealth higher than empireDetection print "invasion AI couldn't access any info for planet id %d" % planet_id return [0, 0] sys_partial_vis_turn = universe.getVisibilityTurnsMap(planet.systemID, empire_id).get(fo.visibility.partial, -9999) planet_partial_vis_turn = universe.getVisibilityTurnsMap(planet_id, empire_id).get(fo.visibility.partial, -9999) if planet_partial_vis_turn < sys_partial_vis_turn: print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id # TODO: track detection strength, order new scouting when it goes up return [0, 0] # last time we had partial vis of the system, the planet was stealthed to us species_name = planet.speciesName species = fo.getSpecies(species_name) if not species: # this call iterates over this Empire's available species with which it could colonize after an invasion planet_eval = ColonisationAI.assign_colonisation_values([planet_id], EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, None, empire, detail) pop_val = max(0.75*planet_eval.get(planet_id, [0])[0], ColonisationAI.evaluate_planet(planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_OUTPOST, None, empire, detail)) else: pop_val = ColonisationAI.evaluate_planet(planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, species_name, empire, detail) bld_tally = 0 for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]: bval = building_values.get(bldType, 50) bld_tally += bval detail.append("%s: %d" % (bldType, bval)) p_sys_id = planet.systemID capitol_id = PlanetUtilsAI.get_capital() least_jumps_path = [] clear_path = True if capitol_id: homeworld = universe.getPlanet(capitol_id) if homeworld: home_system_id = homeworld.systemID eval_system_id = planet.systemID if (home_system_id != -1) and (eval_system_id != -1): least_jumps_path = list(universe.leastJumpsPath(home_system_id, eval_system_id, empire_id)) max_jumps = len(least_jumps_path) system_status = foAI.foAIstate.systemStatus.get(p_sys_id, {}) system_fleet_treat = system_status.get('fleetThreat', 1000) system_monster_threat = system_status.get('monsterThreat', 0) sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get('planetThreat', 0) max_path_threat = system_fleet_treat mil_ship_rating = ProductionAI.cur_best_mil_ship_rating() for path_sys_id in least_jumps_path: path_leg_status = foAI.foAIstate.systemStatus.get(path_sys_id, {}) path_leg_threat = path_leg_status.get('fleetThreat', 1000) + path_leg_status.get('monsterThreat', 0) if path_leg_threat > 0.5 * mil_ship_rating: clear_path = False if path_leg_threat > max_path_threat: max_path_threat = path_leg_threat troops = planet.currentMeterValue(fo.meterType.troops) max_troops = planet.currentMeterValue(fo.meterType.maxTroops) this_system = universe.getSystem(p_sys_id) secure_targets = [p_sys_id] + list(this_system.planetIDs) system_secured = False for mission in secure_fleet_missions: if system_secured: break secure_fleet_id = mission.target_id s_fleet = universe.getFleet(secure_fleet_id) if not s_fleet or s_fleet.systemID != p_sys_id: continue for ai_target in mission.get_targets(EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE): target_obj = ai_target.target_obj if (target_obj is not None) and target_obj.id in secure_targets: system_secured = True break if verbose: print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f" % ( planet.name, planet_id, planet.currentMeterValue(fo.meterType.maxShield), system_fleet_treat, system_monster_threat) supply_val = 0 enemy_val = 0 if planet.owner != -1: # value in taking this away from an enemy enemy_val = 20 * (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch)) if p_sys_id in ColonisationAI.annexable_system_ids: # TODO: extend to rings supply_val = 100 elif p_sys_id in ColonisationAI.annexable_ring1: supply_val = 200 elif p_sys_id in ColonisationAI.annexable_ring2: supply_val = 300 elif p_sys_id in ColonisationAI.annexable_ring3: supply_val = 400 if max_path_threat > 0.5 * mil_ship_rating: if max_path_threat < 3 * mil_ship_rating: supply_val *= 0.5 else: supply_val *= 0.2 threat_factor = min(1, 0.2*MilitaryAI.totMilRating/(sys_total_threat+0.001))**2 # devalue invasions that would require too much military force build_time = 4 planned_troops = troops if system_secured else min(troops+max_jumps+build_time, max_troops) if not tech_is_complete("SHP_ORG_HULL"): troop_cost = math.ceil(planned_troops/6.0) * (40*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP)) else: troop_cost = math.ceil(planned_troops/6.0) * (20*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP)) planet_score = retaliation_risk_factor(planet.owner) * threat_factor * max(0, pop_val+supply_val+bld_tally+enemy_val-0.8*troop_cost) if clear_path: planet_score *= 1.5 invasion_score = [planet_score, planned_troops] print invasion_score, "projected Troop Cost:", troop_cost, ", threatFactor: ", threat_factor, ", planet detail ", detail, "popval, supplyval, bldval, enemyval", pop_val, supply_val, bld_tally, enemy_val return invasion_score
def issue_fleet_orders(self): """issues AIFleetOrders which can be issued in system and moves to next one if is possible""" # TODO: priority order_completed = True print "--------------" print "Checking orders for fleet %d (on turn %d), with mission types %s" % (self.target_id, fo.currentTurn(), [AIFleetMissionType.name(mt) for mt in self.get_mission_types()]) print "\t Full Orders are:" for this_order in self.orders: print "\t\t| %s" % this_order print "/t/t------" if AIFleetMissionType.FLEET_MISSION_INVASION in self.get_mission_types(): self._check_retarget_invasion() for fleet_order in self.orders: print "\t| checking Order: %s" % fleet_order order_type = fleet_order.order_type if order_type in [AIFleetOrderType.ORDER_COLONISE, AIFleetOrderType.ORDER_OUTPOST, AIFleetOrderType.ORDER_INVADE]: # TODO: invasion? if self._check_abort_mission(fleet_order): print "\t\t| Aborting fleet order %s" % fleet_order return self.check_mergers(context=str(fleet_order)) if fleet_order.can_issue_order(verbose=True): if order_type == AIFleetOrderType.ORDER_MOVE and order_completed: # only move if all other orders completed print "\t\t| issuing fleet order %s" % fleet_order fleet_order.issue_order() elif order_type not in [AIFleetOrderType.ORDER_MOVE, AIFleetOrderType.ORDER_DEFEND]: print "\t\t| issuing fleet order %s" % fleet_order fleet_order.issue_order() else: print "\t\t| NOT issuing (even though can_issue) fleet order %s" % fleet_order print "\t\t| order status-- execution completed: %s" % fleet_order.execution_completed if not fleet_order.execution_completed: order_completed = False else: # check that we're not held up by a Big Monster print "\t\t| CAN'T issue fleet order %s" % fleet_order if order_type == AIFleetOrderType.ORDER_MOVE: this_system_id = fleet_order.target.target_id this_status = foAI.foAIstate.systemStatus.setdefault(this_system_id, {}) if this_status.get('monsterThreat', 0) > fo.currentTurn() * ProductionAI.cur_best_mil_ship_rating()/4.0: first_mission = self.get_mission_types()[0] if self.get_mission_types() else AIFleetMissionType.FLEET_MISSION_INVALID if (first_mission not in (AIFleetMissionType.FLEET_MISSION_ATTACK, AIFleetMissionType.FLEET_MISSION_MILITARY, AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN, AIFleetMissionType.FLEET_MISSION_SECURE, ) or fleet_order != self.orders[-1] # if this move order is not this mil fleet's final destination, and blocked by Big Monster, release and hope for more effective reassignment ): print "Aborting mission due to being blocked by Big Monster at system %d, threat %d"%(this_system_id, foAI.foAIstate.systemStatus[this_system_id]['monsterThreat']) print "Full set of orders were:" for this_order in self.orders: print "\t\t %s" % this_order self.clear_fleet_orders() self.clear_targets(([-1] + self.get_mission_types()[:1])[-1]) return # moving to another system stops issuing all orders in system where fleet is # move order is also the last order in system if order_type == AIFleetOrderType.ORDER_MOVE: fleet = fo.getUniverse().getFleet(self.target_id) if fleet.systemID != fleet_order.target.target_id: break else: # went through entire order list if order_completed: print "\t| Final order is completed" orders = self.orders last_order = orders[-1] if orders else None universe = fo.getUniverse() if last_order and last_order.order_type == AIFleetOrderType.ORDER_COLONISE: planet = universe.getPlanet(last_order.target.target_id) sys_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, fo.empireID())).get(fo.visibility.partial, -9999) planet_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.id, fo.empireID())).get(fo.visibility.partial, -9999) if planet_partial_vis_turn == sys_partial_vis_turn and not planet.currentMeterValue(fo.meterType.population): print "Potential Error: Fleet %d has tentatively completed its colonize mission but will wait to confirm population." % self.target_id print " Order details are %s" % last_order print " Order is valid: %s ; is Executed : %s; is execution completed: %s " % (last_order.is_valid(), last_order.isExecuted(), last_order.isExecutionCompleted()) if not last_order.is_valid(): source_target = last_order.fleet target_target = last_order.target print " source target validity: %s; target target validity: %s " % (source_target.valid, target_target.valid) if EnumsAI.TargetType.TARGET_SHIP == source_target.target_type: ship_id = source_target.target_id ship = universe.getShip(ship_id) if not ship: print "Ship id %d not a valid ship id" % ship_id print " source target Ship (%d), species %s, can%s colonize" % (ship_id, ship.speciesName, ["not", ""][ship.canColonize]) return # colonize order must not have completed yet clearAll = True last_sys_target = -1 if last_order and last_order.order_type == AIFleetOrderType.ORDER_MILITARY: last_sys_target = last_order.target.target_id # if (AIFleetMissionType.FLEET_MISSION_SECURE in self.get_mission_types()) or # not doing this until decide a way to release from a SECURE mission secure_targets = set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs + AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs) if last_sys_target in secure_targets: # consider a secure mission if last_sys_target in AIstate.colonyTargetedSystemIDs: secure_type = "Colony" elif last_sys_target in AIstate.outpostTargetedSystemIDs: secure_type = "Outpost" elif last_sys_target in AIstate.invasionTargetedSystemIDs: secure_type = "Invasion" elif last_sys_target in AIstate.blockadeTargetedSystemIDs: secure_type = "Blockade" else: secure_type = "Unidentified" print "Fleet %d has completed initial stage of its mission to secure system %d (targeted for %s), may release a portion of ships" % (self.target_id, last_sys_target, secure_type) clearAll = False fleet_id = self.target_id if clearAll: if orders: print "Fleet %d has completed its mission; clearing all orders and targets." % self.target_id print "Full set of orders were:" for this_order in orders: print "\t\t %s" % this_order self.clear_fleet_orders() self.clear_targets(([-1] + self.get_mission_types()[:1])[-1]) if foAI.foAIstate.get_fleet_role(fleet_id) in (AIFleetMissionType.FLEET_MISSION_MILITARY, AIFleetMissionType.FLEET_MISSION_ATTACK, AIFleetMissionType.FLEET_MISSION_DEFEND, AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN, AIFleetMissionType.FLEET_MISSION_SECURE): allocations = MilitaryAI.get_military_fleets(milFleetIDs=[fleet_id], tryReset=False, thisround="Fleet %d Reassignment" % fleet_id) if allocations: MilitaryAI.assign_military_fleets_to_systems(useFleetIDList=[fleet_id], allocations=allocations) else: # no orders print "No Current Orders" else: #TODO: evaluate releasing a smaller portion or none of the ships system_status = foAI.foAIstate.systemStatus.setdefault(last_sys_target, {}) new_fleets = [] threat_present = (system_status.get('totalThreat', 0) != 0) or (system_status.get('neighborThreat', 0) != 0) target_system = universe.getSystem(last_sys_target) if not threat_present and target_system: for pid in target_system.planetIDs: planet = universe.getPlanet(pid) if planet and planet.owner != fo.empireID() and planet.currentMeterValue(fo.meterType.maxDefense) > 0: threat_present = True break if not threat_present: print "No current threat in target system; releasing a portion of ships." new_fleets = FleetUtilsAI.split_fleet(self.target_id) # at least first stage of current task is done; release extra ships for potential other deployments else: print "Threat remains in target system; NOT releasing any ships." new_military_fleets = [] for fleet_id in new_fleets: if foAI.foAIstate.get_fleet_role(fleet_id) in COMBAT_MISSION_TYPES: new_military_fleets.append(fleet_id) allocations = [] if new_military_fleets: allocations = MilitaryAI.get_military_fleets(milFleetIDs=new_military_fleets, tryReset=False, thisround="Fleet Reassignment %s" % new_military_fleets) if allocations: MilitaryAI.assign_military_fleets_to_systems(useFleetIDList=new_military_fleets, allocations=allocations)
def evaluate_invasion_planet(planet_id, empire, secure_fleet_missions, verbose=True): """Return the invasion value (score, troops) of a planet.""" detail = [] building_values = { "BLD_IMPERIAL_PALACE": 1000, "BLD_CULTURE_ARCHIVES": 1000, "BLD_SHIPYARD_BASE": 100, "BLD_SHIPYARD_ORG_ORB_INC": 200, "BLD_SHIPYARD_ORG_XENO_FAC": 200, "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200, "BLD_SHIPYARD_CON_NANOROBO": 300, "BLD_SHIPYARD_CON_GEOINT": 400, "BLD_SHIPYARD_CON_ADV_ENGINE": 1000, "BLD_SHIPYARD_AST": 300, "BLD_SHIPYARD_AST_REF": 1000, "BLD_SHIPYARD_ENRG_SOLAR": 1500, "BLD_INDUSTRY_CENTER": 500, "BLD_GAS_GIANT_GEN": 200, "BLD_SOL_ORB_GEN": 800, "BLD_BLACK_HOLE_POW_GEN": 2000, "BLD_ENCLAVE_VOID": 500, "BLD_NEUTRONIUM_EXTRACTOR": 2000, "BLD_NEUTRONIUM_SYNTH": 2000, "BLD_NEUTRONIUM_FORGE": 1000, "BLD_CONC_CAMP": 100, "BLD_BIOTERROR_PROJECTOR": 1000, "BLD_SHIPYARD_ENRG_COMP": 3000, } # TODO: add more factors, as used for colonization universe = fo.getUniverse() empire_id = empire.empireID max_jumps = 8 planet = universe.getPlanet(planet_id) if planet is None: # TODO: exclude planets with stealth higher than empireDetection print "invasion AI couldn't access any info for planet id %d" % planet_id return [0, 0] sys_partial_vis_turn = universe.getVisibilityTurnsMap( planet.systemID, empire_id).get(fo.visibility.partial, -9999) planet_partial_vis_turn = universe.getVisibilityTurnsMap( planet_id, empire_id).get(fo.visibility.partial, -9999) if planet_partial_vis_turn < sys_partial_vis_turn: print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id # TODO: track detection strength, order new scouting when it goes up return [ 0, 0 ] # last time we had partial vis of the system, the planet was stealthed to us species_name = planet.speciesName species = fo.getSpecies(species_name) if not species: # this call iterates over this Empire's available species with which it could colonize after an invasion planet_eval = ColonisationAI.assign_colonisation_values( [planet_id], EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, None, empire, detail) pop_val = max( 0.75 * planet_eval.get(planet_id, [0])[0], ColonisationAI.evaluate_planet( planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_OUTPOST, None, empire, detail)) else: pop_val = ColonisationAI.evaluate_planet( planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, species_name, empire, detail) bld_tally = 0 for bldType in [ universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs ]: bval = building_values.get(bldType, 50) bld_tally += bval detail.append("%s: %d" % (bldType, bval)) p_sys_id = planet.systemID capitol_id = PlanetUtilsAI.get_capital() least_jumps_path = [] clear_path = True if capitol_id: homeworld = universe.getPlanet(capitol_id) if homeworld: home_system_id = homeworld.systemID eval_system_id = planet.systemID if (home_system_id != -1) and (eval_system_id != -1): least_jumps_path = list( universe.leastJumpsPath(home_system_id, eval_system_id, empire_id)) max_jumps = len(least_jumps_path) system_status = foAI.foAIstate.systemStatus.get(p_sys_id, {}) system_fleet_treat = system_status.get('fleetThreat', 1000) system_monster_threat = system_status.get('monsterThreat', 0) sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get( 'planetThreat', 0) max_path_threat = system_fleet_treat mil_ship_rating = ProductionAI.cur_best_mil_ship_rating() for path_sys_id in least_jumps_path: path_leg_status = foAI.foAIstate.systemStatus.get(path_sys_id, {}) path_leg_threat = path_leg_status.get( 'fleetThreat', 1000) + path_leg_status.get('monsterThreat', 0) if path_leg_threat > 0.5 * mil_ship_rating: clear_path = False if path_leg_threat > max_path_threat: max_path_threat = path_leg_threat troops = planet.currentMeterValue(fo.meterType.troops) max_troops = planet.currentMeterValue(fo.meterType.maxTroops) this_system = universe.getSystem(p_sys_id) secure_targets = [p_sys_id] + list(this_system.planetIDs) system_secured = False for mission in secure_fleet_missions: if system_secured: break secure_fleet_id = mission.target_id s_fleet = universe.getFleet(secure_fleet_id) if not s_fleet or s_fleet.systemID != p_sys_id: continue for ai_target in mission.get_targets( EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE): target_obj = ai_target.target_obj if (target_obj is not None) and target_obj.id in secure_targets: system_secured = True break if verbose: print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f" % ( planet.name, planet_id, planet.currentMeterValue(fo.meterType.maxShield), system_fleet_treat, system_monster_threat) supply_val = 0 enemy_val = 0 if planet.owner != -1: # value in taking this away from an enemy enemy_val = 20 * ( planet.currentMeterValue(fo.meterType.targetIndustry) + 2 * planet.currentMeterValue(fo.meterType.targetResearch)) if p_sys_id in ColonisationAI.annexable_system_ids: # TODO: extend to rings supply_val = 100 elif p_sys_id in ColonisationAI.annexable_ring1: supply_val = 200 elif p_sys_id in ColonisationAI.annexable_ring2: supply_val = 300 elif p_sys_id in ColonisationAI.annexable_ring3: supply_val = 400 if max_path_threat > 0.5 * mil_ship_rating: if max_path_threat < 3 * mil_ship_rating: supply_val *= 0.5 else: supply_val *= 0.2 threat_factor = min( 1, 0.2 * MilitaryAI.totMilRating / (sys_total_threat + 0.001) )**2 # devalue invasions that would require too much military force build_time = 4 planned_troops = troops if system_secured else min( troops + max_jumps + build_time, max_troops) if not tech_is_complete("SHP_ORG_HULL"): troop_cost = math.ceil(planned_troops / 6.0) * ( 40 * (1 + foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP)) else: troop_cost = math.ceil(planned_troops / 6.0) * ( 20 * (1 + foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP)) planet_score = retaliation_risk_factor(planet.owner) * threat_factor * max( 0, pop_val + supply_val + bld_tally + enemy_val - 0.8 * troop_cost) if clear_path: planet_score *= 1.5 invasion_score = [planet_score, planned_troops] print invasion_score, "projected Troop Cost:", troop_cost, ", threatFactor: ", threat_factor, ", planet detail ", detail, "popval, supplyval, bldval, enemyval", pop_val, supply_val, bld_tally, enemy_val return invasion_score
def calculateMilitaryPriority(): """calculates the demand for military ships by military targeted systems""" global unmetThreat universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.get_capital() if capitalID is not None and capitalID != -1: homeworld = universe.getPlanet(capitalID) else: return 0# no capitol (not even a capitol-in-the-making), means can't produce any ships have_l1_weaps = (tech_is_complete("SHP_WEAPON_1_4") or (tech_is_complete("SHP_WEAPON_1_3") and tech_is_complete("SHP_MIL_ROBO_CONT")) or tech_is_complete("SHP_WEAPON_2_1") or tech_is_complete("SHP_WEAPON_4_1")) have_l2_weaps = (tech_is_complete("SHP_WEAPON_2_3") or tech_is_complete("SHP_WEAPON_4_1")) enemies_sighted = foAI.foAIstate.misc.get('enemies_sighted',{}) allottedInvasionTargets = 1+ int(fo.currentTurn()/25) targetPlanetIDs = [pid for pid, pscore, trp in AIstate.invasionTargets[:allottedInvasionTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisablePlanetIDs.items()[:allottedColonyTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisableOutpostIDs.items()[:allottedColonyTargets] ] mySystems = set( AIstate.popCtrSystemIDs ).union( AIstate.outpostSystemIDs ) targetSystems = set( PlanetUtilsAI.get_systems(targetPlanetIDs) ) curShipRating = ProductionAI.cur_best_mil_ship_rating() cSRR = curShipRating**0.5 defense_ships_needed = 0 currentTurn=fo.currentTurn() ships_needed=0 defense_ships_needed = 0 ships_needed_allocation = [] for sysID in mySystems.union(targetSystems) : status=foAI.foAIstate.systemStatus.get( sysID, {} ) myRating = status.get('myFleetRating', 0) my_defenses = status.get('mydefenses', {}).get('overall', 0) baseMonsterThreat = status.get('monsterThreat', 0) #scale monster threat so that in early - mid game big monsters don't over-drive military production monsterThreat = baseMonsterThreat if currentTurn>200: pass elif currentTurn>100: if baseMonsterThreat >=2000: monsterThreat = 2000 + (currentTurn/100.0 - 1) *(baseMonsterThreat-2000) elif currentTurn>30: if baseMonsterThreat >=2000: monsterThreat = 0 else: if baseMonsterThreat >200: monsterThreat = 0 if sysID in mySystems: threatRoot = status.get('fleetThreat', 0)**0.5 + 0.8*status.get('max_neighbor_threat', 0)**0.5 + 0.2*status.get('neighborThreat', 0)**0.5 + monsterThreat**0.5 + status.get('planetThreat', 0)**0.5 else: threatRoot = status.get('fleetThreat', 0)**0.5 + monsterThreat**0.5 + status.get('planetThreat', 0)**0.5 ships_needed_here = math.ceil(( max(0, (threatRoot - (myRating**0.5 + my_defenses**0.5)))**2)/curShipRating) ships_needed += ships_needed_here ships_needed_allocation.append((sysID, ships_needed_here)) if sysID in mySystems: defense_ships_needed += ships_needed_here scale = (75 + ProductionAI.curBestMilShipCost()) / 2.0 #militaryPriority = int( 40 + max(0, 75*unmetThreat / curShipRating) ) part1 = min(1*fo.currentTurn(), 40) part2 = max(0, int(75*ships_needed) ) militaryPriority = part1 + part2 #militaryPriority = min(1*fo.currentTurn(), 40) + max(0, int(scale*ships_needed)) if not have_l1_weaps: militaryPriority /= 2.0 elif not (have_l2_weaps and enemies_sighted): militaryPriority /= 1.5 #print "Calculating Military Priority: 40 + 75 * unmetThreat/curShipRating \n\t Priority: %d \t unmetThreat %.0f curShipRating: %.0f"%(militaryPriority, unmetThreat, curShipRating) fmt_string = "Calculating Military Priority: min(t,40) + %d * ships_needed \n\t Priority: %d \t ships_needed: %d \t defense_ships_needed: %d \t curShipRating: %.0f \t l1_weaps: %s \t enemies_sighted: %s" print fmt_string%(scale, militaryPriority, ships_needed, defense_ships_needed, curShipRating, have_l1_weaps, enemies_sighted) print "Source of milship demand: ", ships_needed_allocation if foAI.foAIstate.aggression < fo.aggression.typical: militaryPriority *= (1.0 + foAI.foAIstate.aggression) / (1.0 + fo.aggression.typical) return max( militaryPriority, 0)
def calculateMilitaryPriority(): """calculates the demand for military ships by military targeted systems""" global unmetThreat universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.get_capital() if capitalID is not None and capitalID != -1: homeworld = universe.getPlanet(capitalID) else: return 0 # no capitol (not even a capitol-in-the-making), means can't produce any ships have_l1_weaps = (tech_is_complete("SHP_WEAPON_1_4") or (tech_is_complete("SHP_WEAPON_1_3") and tech_is_complete("SHP_MIL_ROBO_CONT")) or tech_is_complete("SHP_WEAPON_2_1") or tech_is_complete("SHP_WEAPON_4_1")) have_l2_weaps = (tech_is_complete("SHP_WEAPON_2_3") or tech_is_complete("SHP_WEAPON_4_1")) enemies_sighted = foAI.foAIstate.misc.get('enemies_sighted', {}) allottedInvasionTargets = 1 + int(fo.currentTurn() / 25) targetPlanetIDs = [ pid for pid, pscore, trp in AIstate.invasionTargets[:allottedInvasionTargets] ] + [ pid for pid, pscore in foAI.foAIstate.colonisablePlanetIDs.items() [:allottedColonyTargets] ] + [ pid for pid, pscore in foAI.foAIstate.colonisableOutpostIDs.items() [:allottedColonyTargets] ] mySystems = set(AIstate.popCtrSystemIDs).union(AIstate.outpostSystemIDs) targetSystems = set(PlanetUtilsAI.get_systems(targetPlanetIDs)) curShipRating = ProductionAI.cur_best_mil_ship_rating() cSRR = curShipRating**0.5 defense_ships_needed = 0 currentTurn = fo.currentTurn() ships_needed = 0 defense_ships_needed = 0 ships_needed_allocation = [] for sysID in mySystems.union(targetSystems): status = foAI.foAIstate.systemStatus.get(sysID, {}) myRating = status.get('myFleetRating', 0) my_defenses = status.get('mydefenses', {}).get('overall', 0) baseMonsterThreat = status.get('monsterThreat', 0) #scale monster threat so that in early - mid game big monsters don't over-drive military production monsterThreat = baseMonsterThreat if currentTurn > 200: pass elif currentTurn > 100: if baseMonsterThreat >= 2000: monsterThreat = 2000 + (currentTurn / 100.0 - 1) * (baseMonsterThreat - 2000) elif currentTurn > 30: if baseMonsterThreat >= 2000: monsterThreat = 0 else: if baseMonsterThreat > 200: monsterThreat = 0 if sysID in mySystems: threatRoot = status.get('fleetThreat', 0)**0.5 + 0.8 * status.get( 'max_neighbor_threat', 0)**0.5 + 0.2 * status.get( 'neighborThreat', 0)**0.5 + monsterThreat**0.5 + status.get( 'planetThreat', 0)**0.5 else: threatRoot = status.get('fleetThreat', 0)**0.5 + monsterThreat**0.5 + status.get( 'planetThreat', 0)**0.5 ships_needed_here = math.ceil( (max(0, (threatRoot - (myRating**0.5 + my_defenses**0.5)))**2) / curShipRating) ships_needed += ships_needed_here ships_needed_allocation.append((sysID, ships_needed_here)) if sysID in mySystems: defense_ships_needed += ships_needed_here scale = (75 + ProductionAI.curBestMilShipCost()) / 2.0 #militaryPriority = int( 40 + max(0, 75*unmetThreat / curShipRating) ) part1 = min(1 * fo.currentTurn(), 40) part2 = max(0, int(75 * ships_needed)) militaryPriority = part1 + part2 #militaryPriority = min(1*fo.currentTurn(), 40) + max(0, int(scale*ships_needed)) if not have_l1_weaps: militaryPriority /= 2.0 elif not (have_l2_weaps and enemies_sighted): militaryPriority /= 1.5 #print "Calculating Military Priority: 40 + 75 * unmetThreat/curShipRating \n\t Priority: %d \t unmetThreat %.0f curShipRating: %.0f"%(militaryPriority, unmetThreat, curShipRating) fmt_string = "Calculating Military Priority: min(t,40) + %d * ships_needed \n\t Priority: %d \t ships_needed: %d \t defense_ships_needed: %d \t curShipRating: %.0f \t l1_weaps: %s \t enemies_sighted: %s" print fmt_string % (scale, militaryPriority, ships_needed, defense_ships_needed, curShipRating, have_l1_weaps, enemies_sighted) print "Source of milship demand: ", ships_needed_allocation if foAI.foAIstate.aggression < fo.aggression.typical: militaryPriority *= (1.0 + foAI.foAIstate.aggression) / ( 1.0 + fo.aggression.typical) return max(militaryPriority, 0)
def issue_fleet_orders(self): """issues AIFleetOrders which can be issued in system and moves to next one if is possible""" # TODO: priority order_completed = True print "--------------" print "Checking orders for fleet %d (on turn %d), with mission types %s" % ( self.target_id, fo.currentTurn(), [AIFleetMissionType.name(mt) for mt in self.get_mission_types()]) print "\t Full Orders are:" for this_order in self.orders: print "\t\t| %s" % this_order print "/t/t------" if AIFleetMissionType.FLEET_MISSION_INVASION in self.get_mission_types( ): self._check_retarget_invasion() for fleet_order in self.orders: print "\t| checking Order: %s" % fleet_order order_type = fleet_order.order_type if order_type in [ AIFleetOrderType.ORDER_COLONISE, AIFleetOrderType.ORDER_OUTPOST, AIFleetOrderType.ORDER_INVADE ]: # TODO: invasion? if self._check_abort_mission(fleet_order): print "\t\t| Aborting fleet order %s" % fleet_order return self.check_mergers(context=str(fleet_order)) if fleet_order.can_issue_order(verbose=True): if order_type == AIFleetOrderType.ORDER_MOVE and order_completed: # only move if all other orders completed print "\t\t| issuing fleet order %s" % fleet_order fleet_order.issue_order() elif order_type not in [ AIFleetOrderType.ORDER_MOVE, AIFleetOrderType.ORDER_DEFEND ]: print "\t\t| issuing fleet order %s" % fleet_order fleet_order.issue_order() else: print "\t\t| NOT issuing (even though can_issue) fleet order %s" % fleet_order print "\t\t| order status-- execution completed: %s" % fleet_order.execution_completed if not fleet_order.execution_completed: order_completed = False else: # check that we're not held up by a Big Monster print "\t\t| CAN'T issue fleet order %s" % fleet_order if order_type == AIFleetOrderType.ORDER_MOVE: this_system_id = fleet_order.target.target_id this_status = foAI.foAIstate.systemStatus.setdefault( this_system_id, {}) if this_status.get('monsterThreat', 0) > fo.currentTurn( ) * ProductionAI.cur_best_mil_ship_rating() / 4.0: first_mission = self.get_mission_types( )[0] if self.get_mission_types( ) else AIFleetMissionType.FLEET_MISSION_INVALID if (first_mission not in ( AIFleetMissionType.FLEET_MISSION_ATTACK, AIFleetMissionType.FLEET_MISSION_MILITARY, AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN, AIFleetMissionType.FLEET_MISSION_SECURE, ) or fleet_order != self.orders[ -1] # if this move order is not this mil fleet's final destination, and blocked by Big Monster, release and hope for more effective reassignment ): print "Aborting mission due to being blocked by Big Monster at system %d, threat %d" % ( this_system_id, foAI.foAIstate. systemStatus[this_system_id]['monsterThreat']) print "Full set of orders were:" for this_order in self.orders: print "\t\t %s" % this_order self.clear_fleet_orders() self.clear_targets( ([-1] + self.get_mission_types()[:1])[-1]) return # moving to another system stops issuing all orders in system where fleet is # move order is also the last order in system if order_type == AIFleetOrderType.ORDER_MOVE: fleet = fo.getUniverse().getFleet(self.target_id) if fleet.systemID != fleet_order.target.target_id: break else: # went through entire order list if order_completed: print "\t| Final order is completed" orders = self.orders last_order = orders[-1] if orders else None universe = fo.getUniverse() if last_order and last_order.order_type == AIFleetOrderType.ORDER_COLONISE: planet = universe.getPlanet(last_order.target.target_id) sys_partial_vis_turn = universe.getVisibilityTurnsMap( planet.systemID, fo.empireID()).get(fo.visibility.partial, -9999) planet_partial_vis_turn = universe.getVisibilityTurnsMap( planet.id, fo.empireID()).get(fo.visibility.partial, -9999) if planet_partial_vis_turn == sys_partial_vis_turn and not planet.currentMeterValue( fo.meterType.population): print "Potential Error: Fleet %d has tentatively completed its colonize mission but will wait to confirm population." % self.target_id print " Order details are %s" % last_order print " Order is valid: %s ; is Executed : %s; is execution completed: %s " % ( last_order.is_valid(), last_order.isExecuted(), last_order.isExecutionCompleted()) if not last_order.is_valid(): source_target = last_order.fleet target_target = last_order.target print " source target validity: %s; target target validity: %s " % ( source_target.valid, target_target.valid) if EnumsAI.TargetType.TARGET_SHIP == source_target.target_type: ship_id = source_target.target_id ship = universe.getShip(ship_id) if not ship: print "Ship id %d not a valid ship id" % ship_id print " source target Ship (%d), species %s, can%s colonize" % ( ship_id, ship.speciesName, ["not", ""][ship.canColonize]) return # colonize order must not have completed yet clearAll = True last_sys_target = -1 if last_order and last_order.order_type == AIFleetOrderType.ORDER_MILITARY: last_sys_target = last_order.target.target_id # if (AIFleetMissionType.FLEET_MISSION_SECURE in self.get_mission_types()) or # not doing this until decide a way to release from a SECURE mission secure_targets = set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs + AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs) if last_sys_target in secure_targets: # consider a secure mission if last_sys_target in AIstate.colonyTargetedSystemIDs: secure_type = "Colony" elif last_sys_target in AIstate.outpostTargetedSystemIDs: secure_type = "Outpost" elif last_sys_target in AIstate.invasionTargetedSystemIDs: secure_type = "Invasion" elif last_sys_target in AIstate.blockadeTargetedSystemIDs: secure_type = "Blockade" else: secure_type = "Unidentified" print "Fleet %d has completed initial stage of its mission to secure system %d (targeted for %s), may release a portion of ships" % ( self.target_id, last_sys_target, secure_type) clearAll = False fleet_id = self.target_id if clearAll: if orders: print "Fleet %d has completed its mission; clearing all orders and targets." % self.target_id print "Full set of orders were:" for this_order in orders: print "\t\t %s" % this_order self.clear_fleet_orders() self.clear_targets( ([-1] + self.get_mission_types()[:1])[-1]) if foAI.foAIstate.get_fleet_role(fleet_id) in ( AIFleetMissionType.FLEET_MISSION_MILITARY, AIFleetMissionType.FLEET_MISSION_ATTACK, AIFleetMissionType.FLEET_MISSION_DEFEND, AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN, AIFleetMissionType.FLEET_MISSION_SECURE): allocations = MilitaryAI.get_military_fleets( milFleetIDs=[fleet_id], tryReset=False, thisround="Fleet %d Reassignment" % fleet_id) if allocations: MilitaryAI.assign_military_fleets_to_systems( useFleetIDList=[fleet_id], allocations=allocations) else: # no orders print "No Current Orders" else: #TODO: evaluate releasing a smaller portion or none of the ships system_status = foAI.foAIstate.systemStatus.setdefault( last_sys_target, {}) new_fleets = [] threat_present = (system_status.get('totalThreat', 0) != 0) or (system_status.get( 'neighborThreat', 0) != 0) target_system = universe.getSystem(last_sys_target) if not threat_present and target_system: for pid in target_system.planetIDs: planet = universe.getPlanet(pid) if planet and planet.owner != fo.empireID( ) and planet.currentMeterValue( fo.meterType.maxDefense) > 0: threat_present = True break if not threat_present: print "No current threat in target system; releasing a portion of ships." new_fleets = FleetUtilsAI.split_fleet( self.target_id ) # at least first stage of current task is done; release extra ships for potential other deployments else: print "Threat remains in target system; NOT releasing any ships." new_military_fleets = [] for fleet_id in new_fleets: if foAI.foAIstate.get_fleet_role( fleet_id) in COMBAT_MISSION_TYPES: new_military_fleets.append(fleet_id) allocations = [] if new_military_fleets: allocations = MilitaryAI.get_military_fleets( milFleetIDs=new_military_fleets, tryReset=False, thisround="Fleet Reassignment %s" % new_military_fleets) if allocations: MilitaryAI.assign_military_fleets_to_systems( useFleetIDList=new_military_fleets, allocations=allocations)