def assessShipDesignRole(design): if design.parts.__contains__("CO_OUTPOST_POD"): if design.starlaneSpeed > 0: return AIShipRoleType.SHIP_ROLE_CIVILIAN_OUTPOST else: return AIShipRoleType.SHIP_ROLE_BASE_OUTPOST if design.parts.__contains__("CO_COLONY_POD") or design.parts.__contains__("CO_SUSPEND_ANIM_POD"): if design.starlaneSpeed > 0: return AIShipRoleType.SHIP_ROLE_CIVILIAN_COLONISATION else: return AIShipRoleType.SHIP_ROLE_BASE_COLONISATION if design.parts.__contains__("GT_TROOP_POD"): if design.starlaneSpeed > 0: return AIShipRoleType.SHIP_ROLE_MILITARY_INVASION else: return AIShipRoleType.SHIP_ROLE_BASE_INVASION if design.starlaneSpeed == 0: if design.parts[0] in [ "SH_DEFENSE_GRID", "SH_DEFLECTOR" , "SH_MULTISPEC" ]: return AIShipRoleType.SHIP_ROLE_BASE_DEFENSE else: return AIShipRoleType.SHIP_ROLE_INVALID stats = foAI.foAIstate.getDesignStats(design) rating = stats['attack'] * ( stats['structure'] + stats['shields'] ) if ( "SD_SCOUT" in design.name(False) ) or (rating < 0.2* ProductionAI.curBestMilShipRating()): for part in design.parts: if "DT_DETECTOR" in part: return AIShipRoleType.SHIP_ROLE_CIVILIAN_EXPLORATION if rating > 0: #positive attack stat return AIShipRoleType.SHIP_ROLE_MILITARY else: return AIShipRoleType.SHIP_ROLE_CIVILIAN_EXPLORATION #let this be the default since even without detection part a ship has some inherent
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.getCapital() 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_mod_weaps = ( empire.getTechStatus("SHP_WEAPON_1_4") == fo.techStatus.complete or empire.getTechStatus("SHP_WEAPON_2_1") == fo.techStatus.complete or empire.getTechStatus("SHP_WEAPON_4_1") == fo.techStatus.complete ) allottedInvasionTargets = 1+ int(fo.currentTurn()/25) targetPlanetIDs = [pid for pid, pscore, trp in AIstate.invasionTargets[:allottedInvasionTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisablePlanetIDs[:allottedColonyTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisableOutpostIDs[:allottedColonyTargets] ] mySystems = set( AIstate.popCtrSystemIDs ).union( AIstate.outpostSystemIDs ) targetSystems = set( PlanetUtilsAI.getSystems(targetPlanetIDs) ) curShipRating = ProductionAI.curBestMilShipRating() cSRR = curShipRating**0.5 unmetThreat = 0.0 currentTurn=fo.currentTurn() shipsNeeded=0 defenses_needed = 0 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 if currentTurn>200: monsterThreat = baseMonsterThreat elif currentTurn>100: if baseMonsterThreat <2000: monsterThreat = baseMonsterThreat else: monsterThreat = 2000 + (currentTurn/100.0 - 1) *(baseMonsterThreat-2000) else: 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 shipsNeeded += math.ceil(( max(0, (threatRoot - (myRating**0.5 + my_defenses**0.5)))**2)/curShipRating) #militaryPriority = int( 40 + max(0, 75*unmetThreat / curShipRating) ) militaryPriority = int( 40 + max(0, 75*shipsNeeded) ) if not have_mod_weaps: militaryPriority /= 2 #print "Calculating Military Priority: 40 + 75 * unmetThreat/curShipRating \n\t Priority: %d \t unmetThreat %.0f curShipRating: %.0f"%(militaryPriority, unmetThreat, curShipRating) print "Calculating Military Priority: 40 + 75 * shipsNeeded \n\t Priority: %d \t shipsNeeded %d \t unmetThreat %.0f curShipRating: %.0f"%(militaryPriority, shipsNeeded, unmetThreat, curShipRating) return max( militaryPriority, 0)
def calculateMilitaryPriority(): "calculates the demand for military ships by military targeted systems" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() if capitalID: homeworld = universe.getPlanet(capitalID) else: return 0# no capitol (not even a capitol-in-the-making), means can't produce any ships allottedInvasionTargets = 1+ int(fo.currentTurn()/25) targetPlanetIDs = [pid for pid, pscore, trp in AIstate.invasionTargets[:allottedInvasionTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisablePlanetIDs[:allottedColonyTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisableOutpostIDs[:allottedColonyTargets] ] mySystems = set( AIstate.popCtrSystemIDs ).union( AIstate.outpostSystemIDs ) targetSystems = set( PlanetUtilsAI.getSystems(targetPlanetIDs) ) curShipRating = ProductionAI.curBestMilShipRating() cSRR = curShipRating**0.5 unmetThreat = 0.0 currentTurn=fo.currentTurn() shipsNeeded=0 for sysID in mySystems.union(targetSystems) : status=foAI.foAIstate.systemStatus.get( sysID, {} ) myAttack, myHealth =0, 0 for fid in status.get('myfleets', []) : rating= foAI.foAIstate.fleetStatus.get(fid, {}).get('rating', {}) myAttack += rating.get('attack', 0) myHealth += rating.get('health', 0) myRating = myAttack*myHealth baseMonsterThreat = status.get('monsterThreat', 0) if currentTurn>200: monsterThreat = baseMonsterThreat elif currentTurn>100: if baseMonsterThreat <2000: monsterThreat = baseMonsterThreat else: monsterThreat = 2000 + (currentTurn/100.0 - 1) *(baseMonsterThreat-2000) else: monsterThreat = 0 threatRoot = status.get('fleetThreat', 0)**0.5 + status.get('planetThreat', 0)**0.5 + monsterThreat**0.5 if sysID in mySystems: threatRoot += (0.3* status.get('neighborThreat', 0))**0.5 else: threatRoot += (0.1* status.get('neighborThreat', 0))**0.5 threat = threatRoot**2 unmetThreat += max( 0, threat - myRating ) shipsNeeded += math.ceil( max(0, (threatRoot/cSRR)- (myRating/curShipRating)**0.5 ) ) #militaryPriority = int( 40 + max(0, 75*unmetThreat / curShipRating) ) militaryPriority = int( 40 + max(0, 75*shipsNeeded) ) #print "Calculating Military Priority: 40 + 75 * unmetThreat/curShipRating \n\t Priority: %d \t unmetThreat %.0f curShipRating: %.0f"%(militaryPriority, unmetThreat, curShipRating) print "Calculating Military Priority: 40 + 75 * shipsNeeded \n\t Priority: %d \t shipsNeeded %d \t unmetThreat %.0f curShipRating: %.0f"%(militaryPriority, shipsNeeded, unmetThreat, curShipRating) return max( militaryPriority, 0)
def getFleetRole(self, fleetID, forceNew=False): "returns fleet role by ID" if (not forceNew) and fleetID in self.__fleetRoleByID and self.__fleetRoleByID[fleetID]!=AIFleetMissionType.FLEET_MISSION_INVALID : return self.__fleetRoleByID[fleetID] else: role=FleetUtilsAI.assessFleetRole(fleetID) self.__fleetRoleByID[fleetID] = role makeAggressive=False if role in [AIFleetMissionType.FLEET_MISSION_COLONISATION, AIFleetMissionType.FLEET_MISSION_OUTPOST, AIFleetMissionType.FLEET_MISSION_ORBITAL_OUTPOST]: pass if role in [AIFleetMissionType.FLEET_MISSION_EXPLORATION]: thisRating=self.getRating(fleetID) if float(thisRating.get('overall', 0))/thisRating.get('nships', 1) >= 0.5 * ProductionAI.curBestMilShipRating(): makeAggressive=True else: makeAggressive=True fo.issueAggressionOrder(fleetID, makeAggressive) return role
def getColonyFleets(): global empireSpecies, empireColonizers, empireSpeciesSystems, annexableSystemIDs, annexableRing1, annexableRing2, annexableRing3 global annexablePlanetIDs, curBestMilShipRating curBestMilShipRating = ProductionAI.curBestMilShipRating() "get colony fleets" allColonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION) AIstate.colonyFleetIDs[:] = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allColonyFleetIDs) # get suppliable systems and planets universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() #capitalID = empire.capitalID homeworld=None if capitalID: homeworld = universe.getPlanet(capitalID) if homeworld: speciesName = homeworld.speciesName homeworldName=homeworld.name homeSystemID = homeworld.systemID else: speciesName = "" homeworldName=" no remaining homeworld " homeSystemID = -1 if not speciesName: speciesName = foAI.foAIstate.origSpeciesName species = fo.getSpecies(speciesName) if not species: print "**************************************************************************************" print "**************************************************************************************" print "Problem determining species for colonization planning: capitalID: %s, homeworld %s and species name %s"%(capitalID, homeworldName, speciesName) else: print "Plannning colonization for species name %s"%species.name fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs) print "" print " fleetSupplyableSystemIDs: " + str(list(fleetSupplyableSystemIDs)) print " fleetSupplyablePlanetIDs: " + str(fleetSupplyablePlanetIDs) print "" print "-------\nEmpire Obstructed Starlanes:" print list(empire.obstructedStarlanes()) annexableSystemIDs.clear() annexableRing1.clear() annexableRing2.clear() annexableRing3.clear() annexablePlanetIDs.clear() for sysID in empire.fleetSupplyableSystemIDs: annexableSystemIDs.add(sysID) for nID in universe.getImmediateNeighbors(sysID, empireID): annexableSystemIDs.add(nID) annexableRing1.add(nID) annexableRing1.difference_update(empire.fleetSupplyableSystemIDs) print "First Ring of annexable systems: ", PlanetUtilsAI.sysNameIDs(annexableRing1) if empire.getTechStatus("CON_ORBITAL_CON") == fo.techStatus.complete: for sysID in list(annexableRing1): for nID in universe.getImmediateNeighbors(sysID, empireID): annexableRing2.add(nID) annexableRing2.difference_update(annexableSystemIDs) print "Second Ring of annexable systems: ", PlanetUtilsAI.sysNameIDs(annexableRing2) annexableSystemIDs.update(annexableRing2) if foAI.foAIstate.aggression > fo.aggression.cautious: for sysID in list(annexableRing2): for nID in universe.getImmediateNeighbors(sysID, empireID): annexableRing3.add(nID) annexableRing3.difference_update(annexableSystemIDs) print "Third Ring of annexable systems: ", PlanetUtilsAI.sysNameIDs(annexableRing3) annexableSystemIDs.update(annexableRing3) annexablePlanetIDs.update( PlanetUtilsAI.getPlanetsInSystemsIDs(annexableSystemIDs)) # get outpost and colonization planets exploredSystemIDs = foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_EXPLORED) unExSysIDs = list(foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)) unExSystems = map(universe.getSystem, unExSysIDs) print "Unexplored Systems: %s " % [(sysID, (sys and sys.name) or "name unknown") for sysID, sys in zip( unExSysIDs, unExSystems)] print "Explored SystemIDs: " + str(list(exploredSystemIDs)) exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs) print "Explored PlanetIDs: " + str(exploredPlanetIDs) print "" #visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() #visiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(visibleSystemIDs) #print "VisiblePlanets: %s "%[ (pid, (universe.getPlanet(pid) and universe.getPlanet(pid).name) or "unknown") for pid in visiblePlanetIDs] #print "" #accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if universe.systemsConnected(sysID, homeSystemID, empireID) ] #acessiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(accessibleSystemIDs) empireOwnedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) print "Empire Owned PlanetIDs: " + str(empireOwnedPlanetIDs) #allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(exploredPlanetIDs) #working with Explored systems not all 'visible' because might not have a path to the latter allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(annexablePlanetIDs) # print "All annexable Owned or Populated PlanetIDs: " + str(set(allOwnedPlanetIDs)-set(empireOwnedPlanetIDs)) #unOwnedPlanetIDs = list(set(exploredPlanetIDs) -set(allOwnedPlanetIDs)) unOwnedPlanetIDs = list(set(annexablePlanetIDs) -set(allOwnedPlanetIDs)) print "UnOwned annexable PlanetIDs: " + str(PlanetUtilsAI.planetNameIDs(unOwnedPlanetIDs)) empirePopCtrs = set( PlanetUtilsAI.getPopulatedPlanetIDs( empireOwnedPlanetIDs) ) empireOutpostIDs=set(empireOwnedPlanetIDs) - empirePopCtrs AIstate.popCtrIDs[:]=list(empirePopCtrs) AIstate.popCtrSystemIDs[:]=list(set(PlanetUtilsAI.getSystems(empirePopCtrs))) AIstate.outpostIDs[:]=list(empireOutpostIDs) AIstate.outpostSystemIDs[:]=list(set(PlanetUtilsAI.getSystems(empireOutpostIDs))) AIstate.colonizedSystems.clear() for pid in empireOwnedPlanetIDs: planet=universe.getPlanet(pid) if planet: AIstate.colonizedSystems.setdefault(planet.systemID, []).append(pid) # track these to plan Solar Generators and Singularity Generators AIstate.empireStars.clear() for sysID in AIstate.colonizedSystems: system = universe.getSystem(sysID) if system: AIstate.empireStars.setdefault(system.starType, []).append(sysID) oldPopCtrs=[] for specN in empireSpecies: oldPopCtrs.extend(empireSpecies[specN]) oldEmpSpec = empireSpecies empireSpecies.clear() oldEmpCol=empireColonizers empireColonizers.clear() if empire.getTechStatus(TechsListsAI.exobotTechName) == fo.techStatus.complete: empireColonizers["SP_EXOBOT"]=[]# get it into colonizer list even if no colony yet empireSpeciesSystems.clear() for pID in empirePopCtrs: planet=universe.getPlanet(pID) if not planet: print "Error empire has apparently lost sight of former colony at planet %d but doesn't realize it"%pID continue pSpecName=planet.speciesName if pID not in oldPopCtrs: if (AIFocusType.FOCUS_MINING in planet.availableFoci): fo.issueChangeFocusOrder(pID, AIFocusType.FOCUS_MINING) print "Changing focus of newly settled planet ID %d : %s to mining "%(pID, planet.name ) empireSpecies[pSpecName] = empireSpecies.get(pSpecName, [])+[pID] print "\n"+"Empire species roster:" for specName in empireSpecies: thisSpec=fo.getSpecies(specName) if thisSpec: shipyards=[] for pID in empireSpecies[specName]: planet=universe.getPlanet(pID) if thisSpec.canColonize: if "BLD_SHIPYARD_BASE" in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]: shipyards.append(pID) empireSpeciesSystems.setdefault(planet.systemID, {}).setdefault('pids', []).append(pID) if thisSpec.canColonize: empireColonizers[specName]=shipyards print "%s on planets %s; can%s colonize from %d shipyards; has tags %s"%(specName, empireSpecies[specName], ["not", ""][thisSpec.canColonize], len(shipyards), list(thisSpec.tags)) else: print "Unable to retrieve info for Species named %s"%specName print"" if empireSpecies!=oldEmpSpec: print "Old empire species: %s ; new empire species: %s"%(oldEmpSpec, empireSpecies) if empireColonizers!=oldEmpCol: print "Old empire colonizers: %s ; new empire colonizers: %s"%(oldEmpCol, empireColonizers) print # export colony targeted systems for other AI modules colonyTargetedPlanetIDs = getColonyTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION, empireID) allColonyTargetedSystemIDs = PlanetUtilsAI.getSystems(colonyTargetedPlanetIDs) AIstate.colonyTargetedSystemIDs = allColonyTargetedSystemIDs print "" print "Colony Targeted SystemIDs: " + str(AIstate.colonyTargetedSystemIDs) print "Colony Targeted PlanetIDs: " + str(colonyTargetedPlanetIDs) colonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION) if not colonyFleetIDs: print "Available Colony Fleets: 0" else: print "Colony FleetIDs: " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)) numColonyFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(colonyFleetIDs)) print "Colony Fleets Without Missions: " + str(numColonyFleets) outpostTargetedPlanetIDs = getOutpostTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, empireID) allOutpostTargetedSystemIDs = PlanetUtilsAI.getSystems(outpostTargetedPlanetIDs) # export outpost targeted systems for other AI modules AIstate.outpostTargetedSystemIDs = allOutpostTargetedSystemIDs print "" print "Outpost Targeted SystemIDs: " + str(AIstate.outpostTargetedSystemIDs) print "Outpost Targeted PlanetIDs: " + str(outpostTargetedPlanetIDs) outpostFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST) if not outpostFleetIDs: print "Available Outpost Fleets: 0" else: print "Outpost FleetIDs: " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST)) numOutpostFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(outpostFleetIDs)) print "Outpost Fleets Without Missions: " + str(numOutpostFleets) evaluatedColonyPlanetIDs = list(set(unOwnedPlanetIDs).union(empireOutpostIDs) - set(colonyTargetedPlanetIDs) ) # print "Evaluated Colony PlanetIDs: " + str(evaluatedColonyPlanetIDs) evaluatedOutpostPlanetIDs = list(set(unOwnedPlanetIDs) - set(outpostTargetedPlanetIDs)- set(colonyTargetedPlanetIDs)) # print "Evaluated Outpost PlanetIDs: " + str(evaluatedOutpostPlanetIDs) evaluatedColonyPlanets = assignColonisationValues(evaluatedColonyPlanetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION, fleetSupplyablePlanetIDs, species, empire) removeLowValuePlanets(evaluatedColonyPlanets) sortedPlanets = evaluatedColonyPlanets.items() sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True) print "" print "Settleable Colony Planets (score,species) | ID | Name | Specials:" for ID, score in sortedPlanets: print " %15s | %5s | %s | %s "%(score, ID, universe.getPlanet(ID).name , list(universe.getPlanet(ID).specials)) print "" # export planets for other AI modules foAI.foAIstate.colonisablePlanetIDs = sortedPlanets#TODO: should include species designation corresponding to rating # get outpost fleets allOutpostFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST) AIstate.outpostFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allOutpostFleetIDs) evaluatedOutpostPlanets = assignColonisationValues(evaluatedOutpostPlanetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, fleetSupplyablePlanetIDs, species, empire) removeLowValuePlanets(evaluatedOutpostPlanets) #bad! lol, was preventing all mining outposts sortedOutposts = evaluatedOutpostPlanets.items() sortedOutposts.sort(lambda x, y: cmp(x[1], y[1]), reverse=True) print "Settleable Outpost PlanetIDs:" for ID, score in sortedOutposts: print " %5s | %5s | %s | %s "%(score, ID, universe.getPlanet(ID).name , list(universe.getPlanet(ID).specials)) print "" # export outposts for other AI modules foAI.foAIstate.colonisableOutpostIDs = sortedOutposts
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)" % (self.target_id, fo.currentTurn()) print "\t Full Orders are:" for this_orders in self.orders: print "\t\t %s" % this_orders print "/t/t------" if AIFleetMissionType.FLEET_MISSION_INVASION in self.get_mission_types(): self._check_retarget_invasion() for fleet_order in self.orders: print " checking Order: %s" % fleet_order order_type = fleet_order.get_fleet_order_type() if order_type in [AIFleetOrderType.ORDER_COLONISE, AIFleetOrderType.ORDER_OUTPOST, AIFleetOrderType.ORDER_INVADE]: # TODO: invasion? if self._check_abort_mission(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 fleet_order.issue_order() elif order_type not in [AIFleetOrderType.ORDER_MOVE, AIFleetOrderType.ORDER_DEFEND]: fleet_order.issue_order() if not fleet_order.is_execution_completed(): order_completed = False else: # check that we're not held up by a Big Monster if order_type == AIFleetOrderType.ORDER_MOVE: this_system_id = fleet_order.get_target_target().target_id this_status = foAI.foAIstate.systemStatus.setdefault(this_system_id, {}) if this_status.get('monsterThreat', 0) > fo.currentTurn() * ProductionAI.curBestMilShipRating()/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_orders in self.orders: print "\t\t %s" % this_orders 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.get_target_target().target_id: break else: # went through entire order list if order_completed: orders = self.orders last_order = orders[-1] if orders else None universe = fo.getUniverse() if last_order and last_order.get_fleet_order_type() == AIFleetOrderType.ORDER_COLONISE: planet = universe.getPlanet(last_order.get_target_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.get_source_target() target_target = last_order.get_target_target() print " source target validity: %s; target target validity: %s " % (source_target.valid, target_target.valid) if EnumsAI.AITargetType.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.get_fleet_order_type() == AIFleetOrderType.ORDER_MILITARY: last_sys_target = last_order.get_target_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_orders in orders: print "\t\t %s" % this_orders 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 (AIFleetMissionType.FLEET_MISSION_MILITARY, AIFleetMissionType.FLEET_MISSION_ATTACK, AIFleetMissionType.FLEET_MISSION_DEFEND, AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN, AIFleetMissionType.FLEET_MISSION_SECURE): 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 evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire, secureAIFleetMissions, verbose=True): "return the invasion value (score, troops) of a planet" detail = [] buildingValues = {"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() empireID = empire.empireID maxJumps=8 planet = universe.getPlanet(planetID) if (planet == None) : #TODO: exclude planets with stealth higher than empireDetection print "invasion AI couldn't access any info for planet id %d"%planetID return [0, 0] sysPartialVisTurn = dictFromMap(universe.getVisibilityTurnsMap(planet.systemID, empireID)).get(fo.visibility.partial, -9999) planetPartialVisTurn = dictFromMap(universe.getVisibilityTurnsMap(planetID, empireID)).get(fo.visibility.partial, -9999) if planetPartialVisTurn < sysPartialVisTurn: print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)"%planetID return [0, 0] #last time we had partial vis of the system, the planet was stealthed to us #TODO: track detection strength, order new scouting when it goes up specName=planet.speciesName species=fo.getSpecies(specName) if not species: #this call iterates over this Empire's available species with which it could colonize after an invasion planetEval = ColonisationAI.assignColonisationValues([planetID], EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION, [planetID], None, empire, detail) #evaluatePlanet is imported from ColonisationAI popVal = max( 0.75*planetEval.get(planetID, [0])[0], ColonisationAI.evaluatePlanet(planetID, EnumsAI.AIFleetMissionType.FLEET_MISSION_OUTPOST, [planetID], None, empire, detail) ) else: popVal = ColonisationAI.evaluatePlanet(planetID, EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION, [planetID], specName, empire, detail) #evaluatePlanet is imported from ColonisationAI bldTally=0 for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]: bval = buildingValues.get(bldType, 50) bldTally += bval detail.append("%s: %d"%(bldType, bval)) pSysID = planet.systemID capitolID = PlanetUtilsAI.getCapital() leastJumpsPath = [] clear_path = True if capitolID: homeworld = universe.getPlanet(capitolID) if homeworld: homeSystemID = homeworld.systemID evalSystemID = planet.systemID if (homeSystemID != -1) and (evalSystemID != -1): leastJumpsPath = list(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID)) maxJumps = len(leastJumpsPath) system_status = foAI.foAIstate.systemStatus.get(pSysID, {}) sysFThrt = system_status.get('fleetThreat', 1000 ) sysMThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('monsterThreat', 0 ) sysPThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('planetThreat', 0 ) sysTotThrt = sysFThrt + sysMThrt + sysPThrt max_path_threat = sysFThrt mil_ship_rating = ProductionAI.curBestMilShipRating() for path_sys_id in leastJumpsPath: 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) maxTroops = planet.currentMeterValue(fo.meterType.maxTroops) this_system = universe.getSystem(pSysID) secure_targets = [pSysID] + list(this_system.planetIDs) system_secured = False for mission in secureAIFleetMissions: 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 != pSysID): continue for ai_target in mission.getAITargets(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 pmaxShield = planet.currentMeterValue(fo.meterType.maxShield) if verbose: print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f"%(planet.name, planetID, pmaxShield, sysFThrt, sysMThrt) supplyVal=0 enemyVal=0 if planet.owner!=-1 : #value in taking this away from an enemy enemyVal= 20* (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch)) if pSysID in ColonisationAI.annexableSystemIDs: #TODO: extend to rings supplyVal = 100 elif pSysID in ColonisationAI.annexableRing1: supplyVal = 200 elif pSysID in ColonisationAI.annexableRing2: supplyVal = 300 elif pSysID in ColonisationAI.annexableRing2: supplyVal = 400 if ( max_path_threat > 0.5 * mil_ship_rating ): if ( max_path_threat < 3 * mil_ship_rating ): supplyVal *= 0.5 else: supplyVal *= 0.2 threatFactor = min(1, 0.2*MilitaryAI.totMilRating/(sysTotThrt+0.001))**2 #devalue invasions that would require too much military force buildTime=4 if system_secured: plannedTroops = troops else: plannedTroops = min(troops+maxJumps+buildTime, maxTroops) if ( empire.getTechStatus("SHP_ORG_HULL") != fo.techStatus.complete ): troopCost = math.ceil( plannedTroops/6.0) * ( 40*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) ) else: troopCost = math.ceil( plannedTroops/6.0) * ( 20*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) ) planet_score = threatFactor*max(0, popVal+supplyVal+bldTally+enemyVal-0.8*troopCost) if clear_path: planet_score *= 1.5 invscore = [ planet_score, plannedTroops ] print invscore, "projected Troop Cost:", troopCost, ", threatFactor: ", threatFactor, ", planet detail ", detail, "popval, supplyval, bldval, enemyval", popVal, supplyVal, bldTally, enemyVal return invscore
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire): "return the invasion value of a planet" detail = [] buildingValues = {"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": 150, "BLD_SHIPYARD_AST_REF": 500, "BLD_SHIPYARD_ENRG_COMP": 500, "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() empireID = empire.empireID maxJumps=8 planet = universe.getPlanet(planetID) if (planet == None) : #TODO: exclude planets with stealth higher than empireDetection print "invasion AI couldn't get current info on planet %d"%planetID return 0, 0 specName=planet.speciesName species=fo.getSpecies(specName) if not species:#TODO: probably stealth makes planet inacccesible & should abort return 0, 0 else: popVal = ColonisationAI.evaluatePlanet(planetID, EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION, [planetID], species, empire, detail) #evaluatePlanet is imported from ColonisationAI bldTally=0 for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]: bval = buildingValues.get(bldType, 50) bldTally += bval detail.append("%s: %d"%(bldType, bval)) capitolID = PlanetUtilsAI.getCapital() if capitolID: homeworld = universe.getPlanet(capitolID) if homeworld: homeSystemID = homeworld.systemID evalSystemID = planet.systemID leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID)) maxJumps = leastJumpsPath troops = planet.currentMeterValue(fo.meterType.troops) maxTroops = planet.currentMeterValue(fo.meterType.maxTroops) popTSize = planet.currentMeterValue(fo.meterType.targetPopulation)#TODO: adjust for empire tech planetSpecials = list(planet.specials) pSysID = planet.systemID#TODO: check star value pmaxShield = planet.currentMeterValue(fo.meterType.maxShield) sysFThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('fleetThreat', 1000 ) sysMThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('monsterThreat', 0 ) print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f"%(planet.name, planetID, pmaxShield, sysFThrt, sysMThrt) supplyVal=0 enemyVal=0 if planet.owner!=-1 : #value in taking this away from an enemy enemyVal= 20* (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch)) if planetID in fleetSupplyablePlanetIDs: #TODO: extend to rings supplyVal = 100 if planet.owner== -1: #if (pmaxShield <10): if ( sysFThrt < 0.5*ProductionAI.curBestMilShipRating() ): if ( sysMThrt < 3*ProductionAI.curBestMilShipRating()): supplyVal = 50 else: supplyVal = 20 else: supplyVal *= int( min(1, ProductionAI.curBestMilShipRating() / sysFThrt ) ) buildTime=4 plannedTroops = min(troops+maxJumps+buildTime, maxTroops) if ( empire.getTechStatus("SHP_ORG_HULL") != fo.techStatus.complete ): troopCost = math.ceil( plannedTroops/6.0) * ( 40*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) ) else: troopCost = math.ceil( plannedTroops/6.0) * ( 20*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) ) invscore = max(0, popVal+supplyVal+bldTally+enemyVal-0.8*troopCost), plannedTroops print invscore, "projected Troop Cost:", troopCost, "planet detail ", detail, popVal, supplyVal, bldTally, enemyVal return invscore
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_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[:allottedColonyTargets] ] + [pid for pid, pscore in foAI.foAIstate.colonisableOutpostIDs[:allottedColonyTargets] ] mySystems = set( AIstate.popCtrSystemIDs ).union( AIstate.outpostSystemIDs ) targetSystems = set( PlanetUtilsAI.get_systems(targetPlanetIDs) ) curShipRating = ProductionAI.curBestMilShipRating() 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 issueAIFleetOrders(self): "issues AIFleetOrders which can be issued in system and moves to next one if is possible" # TODO: priority ordersCompleted = True print "Checking orders for fleet %d"%(self.getAITargetID()) #print "\t Full Orders are:" #for aiFleetOrder2 in self.getAIFleetOrders(): # print "\t\t %s"%aiFleetOrder2 for aiFleetOrder in self.getAIFleetOrders(): print " %s"%(aiFleetOrder) clearAll=False if aiFleetOrder.getAIFleetOrderType() in [EnumsAI.AIFleetOrderType.ORDER_COLONISE, EnumsAI.AIFleetOrderType.ORDER_OUTPOST]:#TODO: invasion? universe=fo.getUniverse() planet = universe.getPlanet(aiFleetOrder.getTargetAITarget().getTargetID()) if not planet: clearAll =True elif aiFleetOrder.getAIFleetOrderType() == EnumsAI.AIFleetOrderType.ORDER_COLONISE : if ( (planet.currentMeterValue(fo.meterType.population) >0) or not ( planet.unowned or planet.ownedBy(fo.empireID()) ) ) : clearAll =True elif not planet.unowned: clearAll =True if clearAll: print "Fleet %d had a target planet that is no longer valid for this mission; aborting."%(self.getAITargetID() ) self.clearAIFleetOrders() self.clearAITargets(([-1]+ self.getAIMissionTypes()[:1])[-1]) FleetUtilsAI.splitFleet(self.getAITargetID() ) return self.checkMergers(context=str(aiFleetOrder)) if aiFleetOrder.canIssueOrder(verbose=True): #print " " + str(aiFleetOrder) currently already printed in canIssueOrder() if aiFleetOrder.getAIFleetOrderType() == EnumsAI.AIFleetOrderType.ORDER_MOVE and ordersCompleted: #only move if all other orders completed aiFleetOrder.issueOrder() elif aiFleetOrder.getAIFleetOrderType() not in [ EnumsAI.AIFleetOrderType.ORDER_MOVE, EnumsAI.AIFleetOrderType.ORDER_DEFEND]: aiFleetOrder.issueOrder() if not aiFleetOrder.isExecutionCompleted(): ordersCompleted = False else: #check that we're not held up by a Big Monster if aiFleetOrder.getAIFleetOrderType() == EnumsAI.AIFleetOrderType.ORDER_MOVE: thisSysID = aiFleetOrder.getTargetAITarget().getTargetID() thisStatus = foAI.foAIstate.systemStatus.setdefault(thisSysID, {}) if ( thisStatus.get('monsterThreat', 0) > fo.currentTurn() * ProductionAI.curBestMilShipRating()/4.0 ) : if ( ( (self.getAIMissionTypes() + [-1] )[0] not in [ EnumsAI.AIFleetMissionType.FLEET_MISSION_ATTACK, EnumsAI.AIFleetMissionType.FLEET_MISSION_MILITARY, EnumsAI.AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN, EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE, ]) or ( aiFleetOrder != self.getAIFleetOrders()[-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"%(thisSysID, foAI.foAIstate.systemStatus[thisSysID]['monsterThreat']) print "Full set of orders were:" for aiFleetOrder2 in self.getAIFleetOrders(): print "\t\t %s"%aiFleetOrder2 self.clearAIFleetOrders() self.clearAITargets(([-1]+ self.getAIMissionTypes()[: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 aiFleetOrder.getAIFleetOrderType() == EnumsAI.AIFleetOrderType.ORDER_MOVE: fleet = fo.getUniverse().getFleet( self.getAITargetID() ) if fleet.systemID != aiFleetOrder.getTargetAITarget().getTargetID(): break else: #went through entire order list if ordersCompleted: orders=self.getAIFleetOrders() lastOrder= orders and orders[-1] if orders and lastOrder.getAIFleetOrderType() == EnumsAI.AIFleetOrderType.ORDER_COLONISE: universe=fo.getUniverse() planet = universe.getPlanet(lastOrder.getTargetAITarget().getTargetID()) pop=planet.currentMeterValue(fo.meterType.population) if pop==0: print "Fleet %d has tentatively completed its colonize mission but will wait to confirm population."%(self.getAITargetID() ) print " Order details are %s"%lastOrder print " Order is valid: %s ; is Executed : %s ; is execution completed: %s "%(lastOrder.isValid(), lastOrder.isExecuted(), lastOrder.isExecutionCompleted()) if not lastOrder.isValid(): sourceT = lastOrder.getSourceAITarget() targT = lastOrder.getTargetAITarget() print " source target validity: %s ; target target validity: %s "%(sourceT.isValid() , targT.isValid()) if EnumsAI.AITargetType.TARGET_SHIP == sourceT: shipID = sourceT.getTargetID() ship = universe.getShip(shipID) if not ship: print "Ship id %d not a valid ship id"%(shipID) print " source target Ship (%d), species %s, can%s colonize"%( shipID, ship.speciesName, ["not", ""][ship.canColonize]) return # colonize order must not have completed yet clearAll=True if orders and lastOrder.getAIFleetOrderType() == EnumsAI.AIFleetOrderType.ORDER_MILITARY: # if (AIFleetMissionType.FLEET_MISSION_SECURE in self.getAIMissionTypes()) or # not doing this until decide a way to release from a SECURE mission if (lastOrder.getTargetAITarget().getTargetID() in list(set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs + AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs))): #consider a secure mission print "Fleet %d has completed initial stage of its mission to secure system %d, may release a portion of ships"%(self.getAITargetID() , lastOrder.getTargetAITarget().getTargetID()) clearAll=False if clearAll: print "Fleet %d has completed its mission; clearing all orders and targets."%(self.getAITargetID() ) print "Full set of orders were:" for aiFleetOrder2 in self.getAIFleetOrders(): print "\t\t %s"%aiFleetOrder2 self.clearAIFleetOrders() self.clearAITargets(([-1]+ self.getAIMissionTypes()[:1])[-1]) else: #TODO: evaluate releasing a smaller portion or none of the ships FleetUtilsAI.splitFleet(self.getAITargetID() ) #at least first stage of current task is done; release extra ships for potential other deployments
def evaluatePlanet(planetID, missionType, fleetSupplyablePlanetIDs, species, empire): "returns the colonisation value of a planet" # TODO: in planet evaluation consider specials and distance valMod = 0 universe = fo.getUniverse() empireResearchList = [element.tech for element in empire.researchQueue] planet = universe.getPlanet(planetID) if (planet == None): return 0 system = universe.getSystem(planet.systemID) tagList=[] starBonus=0 if species: tagList = [tag for tag in species.tags] if system: if (empire.getTechStatus("PRO_SOL_ORB_GEN") == fo.techStatus.complete) or ( "PRO_SOL_ORB_GEN" in empireResearchList[:8]) : if system.starType in [fo.starType.blue, fo.starType.white]: if len (AIstate.empireStars.get(fo.starType.blue, [])+AIstate.empireStars.get(fo.starType.white, []))==0: starBonus +=40 else: starBonus +=5 #still has extra value as an alternate location for solar generators if system.starType in [fo.starType.yellow, fo.starType.orange]: if len ( AIstate.empireStars.get(fo.starType.blue, [])+AIstate.empireStars.get(fo.starType.white, [])+ AIstate.empireStars.get(fo.starType.yellow, [])+AIstate.empireStars.get(fo.starType.orange, []))==0: starBonus +=10 else: starBonus +=2 #still has extra value as an alternate location for solar generators if (empire.getTechStatus("PRO_SINGULAR_GEN") == fo.techStatus.complete) or ( "PRO_SINGULAR_GEN" in empireResearchList[:8]) : if system.starType in [fo.starType.blackHole]: if len (AIstate.empireStars.get(fo.starType.blackHole, []))==0: starBonus +=80 #pretty rare planets, good for generator else: starBonus +=20 #still has extra value as an alternate location for generators & for bnlocking enemies generators if (empire.getTechStatus("PRO_NEUTRONIUM_EXTRACTION") == fo.techStatus.complete) or ( "PRO_NEUTRONIUM_EXTRACTION" in empireResearchList[:8]) : if system.starType in [fo.starType.neutron]: if len (AIstate.empireStars.get(fo.starType.neutron, []))==0: starBonus +=40 #pretty rare planets, good for armor else: starBonus +=5 #still has extra value as an alternate location for generators & for bnlocking enemies generators retval = starBonus planetSpecials = list(planet.specials) if (missionType == AIFleetMissionType.FLEET_MISSION_OUTPOST ): for special in planetSpecials: if "_NEST_" in special: retval+=10 # get an outpost on the nest quick if ( ( planet.size == fo.planetSize.asteroids ) and (empire.getTechStatus("PRO_MICROGRAV_MAN") == fo.techStatus.complete )): retval+=10*len( empireSpeciesSystems.get(planet.systemID , [])) # asteroid mining is good return #TODO: check that no preexisting asteroid outpost in system for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : if special in planetSpecials: retval += 30 #expects we can make exobots soonish or will have other colonizers & want to claim the planet if ( ( planet.size == fo.planetSize.gasGiant ) and ( (empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete ) or ( "PRO_ORBITAL_GEN" in empireResearchList[:10]) )): retval += 45*len( empireSpeciesSystems.get(planet.systemID , [])) # gias giant generators great, fast return if foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0) > 0: retval = retval / 2.0 return int(retval) else: #colonization mission asteroidBonus=0 gasGiantBonus=0 if (planet.size==fo.planetSize.gasGiant) and not (species and species.name == "SP_SUPER_TEST"): return 0 elif ( planet.size == fo.planetSize.asteroids ): if (species and species.name in [ "SP_EXOBOT", "SP_SUPER_TEST" ]): for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : #even though as of time of writing only crystals can be in asteroids it seems if special in planetSpecials: retval+=60 else: retval+=20 thrtRatio = foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0) / float(ProductionAI.curBestMilShipRating()) if thrtRatio > 4: retval = 2* retval / thrtRatio elif thrtRatio >= 2: retval = 0.6* retval elif thrtRatio > 0: retval = 0.8* retval return int(retval) return 0 if system: for pid in [id for id in system.planetIDs if id != planetID]: p2 = universe.getPlanet(pid) if p2: if p2.size== fo.planetSize.asteroids : asteroidBonus = 5 if p2.size== fo.planetSize.gasGiant : gasGiantBonus += 10 planetEnv = environs[ str(species.getPlanetEnvironment(planet.type)) ] popSizeMod=0 popSizeMod += popSizeModMap["env"][planetEnv] if empire.getTechStatus("GRO_SUBTER_HAB") == fo.techStatus.complete: if "TECTONIC_INSTABILITY_SPECIAL" not in planetSpecials: popSizeMod += popSizeModMap["subHab"][planetEnv] if empire.getTechStatus("GRO_SYMBIOTIC_BIO") == fo.techStatus.complete: popSizeMod += popSizeModMap["symBio"][planetEnv] if empire.getTechStatus("GRO_XENO_GENETICS") == fo.techStatus.complete: popSizeMod += popSizeModMap["xenoGen"][planetEnv] if empire.getTechStatus("GRO_XENO_HYBRID") == fo.techStatus.complete: popSizeMod += popSizeModMap["xenoHyb"][planetEnv] if empire.getTechStatus("GRO_CYBORG") == fo.techStatus.complete: popSizeMod += popSizeModMap["cyborg"][planetEnv] for special in [ "SLOW_ROTATION_SPECIAL", "SOLID_CORE_SPECIAL"] : if special in planetSpecials: popSizeMod -= 1 #have to use these namelists since species tags don't seem available to AI currently #for special, namelist in [ ("PROBIOTIC_SPECIAL", ["SP_HUMAN", "SP_SCYLIOR", "SP_GYISACHE", "SP_HHHOH", "SP_EAXAW"]), # ("FRUIT_SPECIAL", ["SP_HUMAN", "SP_SCYLIOR", "SP_GYISACHE", "SP_HHHOH", "SP_EAXAW", "SP_TRITH"]), # ("SPICE_SPECIAL", ["SP_HUMAN", "SP_SCYLIOR", "SP_GYISACHE", "SP_HHHOH", "SP_EAXAW"]), # ("MONOPOLE_SPECIAL", ["SP_CRAY"]), # ("SUPERCONDUCTOR_SPECIAL", ["SP_CRAY"]), # ("POSITRONIUM_SPECIAL", ["SP_CRAY"]), # ("MINERALS_SPECIAL", ["SP_GEORGE", "SP_EGASSEM"]), # ("METALOIDS_SPECIAL", ["SP_GEORGE", "SP_EGASSEM"]), # ]: for special, tag in [ ("PROBIOTIC_SPECIAL", "ORGANIC"), ("FRUIT_SPECIAL", "ORGANIC"), ("SPICE_SPECIAL", "ORGANIC"), ("MONOPOLE_SPECIAL", "ROBOTIC"), ("SUPERCONDUCTOR_SPECIAL", "ROBOTIC"), ("POSITRONIUM_SPECIAL", "ROBOTIC"), ("MINERALS_SPECIAL", "LITHIC"), ("METALOIDS_SPECIAL", "LITHIC"), ]: if special in planetSpecials: valMod += 5 # extra bonus due to potential applicability to other planets, or to industry if tag in tagList: popSizeMod += 1 # print "planet %s had special %s that triggers pop mod for species %s"%(planet.name, special, species.name) #else: # print "planet %s had special %s without pop mod for species %s"%(planet.name, special, species.name) if "GAIA_SPECIAL" in planet.specials: popSizeMod += 3 popSize = planet.size * popSizeMod if empire.getTechStatus("CON_NDIM_STRUC") == fo.techStatus.complete: popSize += popSizeModMap["ndim"][planetEnv] if empire.getTechStatus("CON_ORBITAL_HAB") == fo.techStatus.complete: popSize += popSizeModMap["orbit"][planetEnv] if "DIM_RIFT_MASTER_SPECIAL" in planet.specials: popSize -= 4 # give preference to closest worlds empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() homeworld = universe.getPlanet(capitalID) if homeworld: homeSystemID = homeworld.systemID evalSystemID = planet.systemID leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID)) distanceFactor = 1.001 / (leastJumpsPath + 1) else: distanceFactor = 0 if foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0) > 0: threatFactor = 0.7 else: threatFactor = 1.0 if popSize<1: return 0 if (planetID in fleetSupplyablePlanetIDs): return (retval+ popSize + distanceFactor + valMod + gasGiantBonus + asteroidBonus)*threatFactor #return getPlanetHospitality(planetID, species) * planet.size + distanceFactor else: return (retval+popSize + distanceFactor + valMod)*threatFactor