def setCapitalIDResourceFocus(): "set resource focus of CapitalID planet" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) capitalID = PlanetUtilsAI.getCapital() topPriority = topResourcePriority() if topPriority == AIPriorityType.PRIORITY_RESOURCE_GROWTH: newFocus = AIFocusType.FOCUS_GROWTH for planetID in empirePlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID == capitalID and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_PRODUCTION: newFocus = AIFocusType.FOCUS_INDUSTRY for planetID in empirePlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID == capitalID and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_RESEARCH: newFocus = AIFocusType.FOCUS_RESEARCH for planetID in empirePlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID == capitalID and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus)
def evaluateSystem(systemID, missionType, empireProvinceSystemIDs, otherTargetedSystemIDs, empire): "return the military value of a system" universe = fo.getUniverse() system = universe.getSystem(systemID) if (system == None): return 0 # give preference to home system then closest systems empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() homeworld = universe.getPlanet(capitalID) if homeworld: homeSystemID = homeworld.systemID evalSystemID = system.systemID leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID)) distanceFactor = 1.001/(leastJumpsPath + 1) else: homeSystemID=-1 distanceFactor=0 if systemID == homeSystemID: return 10 elif systemID in empireProvinceSystemIDs: return 4 + distanceFactor elif systemID in otherTargetedSystemIDs: return 2 + distanceFactor else: return 1 + .25 * distanceFactor
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 getResourceTargetTotals(empirePlanetIDs):#+ universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID #empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) capitalID = PlanetUtilsAI.getCapital() oldTargets.clear() oldTargets.update(newTargets) newTargets.clear() currentFocus.clear() currentOutput.clear() targetPP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetIndustry), planetMap.values()) ) targetRP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetResearch), planetMap.values()) ) newFocus= IFocus for pid in empirePlanetIDs: planet=planetMap[pid] #canFocus= planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0 currentFocus[pid] = planet.focus #if currentFocus[pid] == MFocus: # mtarget=planetMap[pid].currentMeterValue(fo.meterType.targetIndustry) currentOutput.setdefault(pid, {} )[ IFocus] = planet.currentMeterValue(fo.meterType.industry) currentOutput[pid][ RFocus] = planet.currentMeterValue(fo.meterType.research) if IFocus in planet.availableFoci and planet.focus !=IFocus: fo.issueChangeFocusOrder(pid, IFocus) #may not be able to take, but try universe.updateMeterEstimates(empirePlanetIDs) for pid in empirePlanetIDs: planet=planetMap[pid] itarget=planet.currentMeterValue(fo.meterType.targetIndustry) rtarget=planet.currentMeterValue(fo.meterType.targetResearch) if planet.focus == IFocus: newTargets.setdefault(pid, {})[IFocus] = ( itarget, rtarget ) newTargets.setdefault(pid, {})[GFocus] = [0, rtarget] else: newTargets.setdefault(pid, {})[IFocus] = ( 0, 0) newTargets.setdefault(pid, {})[GFocus] = [0, 0] #if currentFocus[pid] == MFocus: # newTargets[pid][MFocus] = ( mtarget, rtarget ) if RFocus in planet.availableFoci and planet.focus!=RFocus: fo.issueChangeFocusOrder(pid, RFocus) #may not be able to take, but try universe.updateMeterEstimates(empirePlanetIDs) for pid in empirePlanetIDs: planet=planetMap[pid] canFocus= planet.currentMeterValue(fo.meterType.targetPopulation) >0 itarget=planet.currentMeterValue(fo.meterType.targetIndustry) rtarget=planet.currentMeterValue(fo.meterType.targetResearch) if planet.focus == RFocus: newTargets.setdefault(pid, {})[RFocus] = ( itarget, rtarget ) newTargets[pid][GFocus][0] = itarget else: newTargets.setdefault(pid, {})[RFocus] = ( 0, 0 ) newTargets[pid][GFocus][0] = 0 if canFocus and currentFocus[pid] != planet.focus: fo.issueChangeFocusOrder(pid, currentFocus[pid]) #put it back to what it was universe.updateMeterEstimates(empirePlanetIDs) return targetPP, targetRP
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 getHomeSystemID(): "returns the systemID of the home world" empire = fo.getEmpire() universe = fo.getUniverse() homeworld = universe.getPlanet(PlanetUtilsAI.getCapital()) if homeworld: return homeworld.systemID return -1
def calculateMilitaryPriority(): "calculates the demand for military ships by military targeted systems" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() homeworld = universe.getPlanet(capitalID) if homeworld: homeSystemID = homeworld.systemID else: homeSystemID=-1 totalThreat = 0 for sysStatus in foAI.foAIstate.systemStatus.values(): totalThreat += max(0, (sysStatus.get('fleetThreat', 0) + sysStatus.get('planetThreat', 0) - 0.7*sysStatus.get('monsterThreat', 0) + sysStatus.get('neighborThreat', 0) )) #being safe; should never be neg since fleetThreat should include monsterThreat totalFleetRating = 0 for fleetStatus in foAI.foAIstate.fleetStatus.values(): totalFleetRating += fleetStatus.get('rating', {}).get('overall', 0) #numMilitaryTargetedSystemIDs = len(AIstate.militaryTargetedSystemIDs) #militaryShipIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_MILITARY) #numMilitaryShips = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(militaryShipIDs)) curShipRating = curBestMilShipRating() if fo.currentTurn() < 20: threatBias = 0 elif fo.currentTurn() < 40: threatBias = 10 elif fo.currentTurn() < 60: threatBias = 80 elif fo.currentTurn() < 80: threatBias = 100 else: threatBias = 200 if threatBias > 0: threatBias = max(threatBias, curShipRating) visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if universe.systemsConnected(sysID, homeSystemID, empireID) ] totalBias = len(accessibleSystemIDs) * threatBias # build one more military ship than military targeted systems #militaryPriority = 100 * ((numMilitaryTargetedSystemIDs +2) - numMilitaryShips) / (numMilitaryTargetedSystemIDs + 1) militaryPriority = int( 40 + max(0, 15*((1.25*totalThreat +threatBias - totalFleetRating ) / curShipRating)) ) print "Military Priority Calc: int( 40 + max(0, 10*((1.25*totalThreat(%d) - totalFleetRating(%d) ) / curShipRating(%d) )) ) = %d"%(totalThreat, totalFleetRating, curShipRating, militaryPriority) # print "" # print "Number of Military Ships Without Missions: " + str(numMilitaryShips) # print "Number of Military Targeted Systems: " + str(numMilitaryTargetedSystemIDs) # print "Priority for Military Ships: " + str(militaryPriority) return max( militaryPriority, 0)
def getResourceTargetTotals(): universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) capitalID = PlanetUtilsAI.getCapital() # planet = universe.getPlanet(planetID) # if planet.currentMeterValue(fo.meterType.population) >0: planets = map(universe.getPlanet, empirePlanetIDs) planetMap = dict( zip( empirePlanetIDs, planets)) oldTargets.clear() oldTargets.update(newTargets) newTargets.clear() currentFocus.clear() currentOutput.clear() targetPP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetIndustry), planets) ) targetRP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetResearch), planets) ) newFocus= IFocus for pid in empirePlanetIDs: canFocus= planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0 currentFocus[pid] = planetMap[pid].focus #if currentFocus[pid] == MFocus: # mtarget=planetMap[pid].currentMeterValue(fo.meterType.targetIndustry) currentOutput.setdefault(pid, {} )[ IFocus] = planetMap[pid].currentMeterValue(fo.meterType.industry) currentOutput[pid][ RFocus] = planetMap[pid].currentMeterValue(fo.meterType.research) if canFocus: fo.issueChangeFocusOrder(pid, IFocus) #may not be able to take, but try universe.updateMeterEstimates(empirePlanetIDs) for pid in empirePlanetIDs: canFocus= planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0 itarget=planetMap[pid].currentMeterValue(fo.meterType.targetIndustry) rtarget=planetMap[pid].currentMeterValue(fo.meterType.targetResearch) newTargets.setdefault(pid, {}).setdefault(IFocus, (0, 0)) newTargets[pid][IFocus] = ( itarget, rtarget ) #if currentFocus[pid] == MFocus: # newTargets[pid][MFocus] = ( mtarget, rtarget ) if canFocus: fo.issueChangeFocusOrder(pid, RFocus) #may not be able to take, but try universe.updateMeterEstimates(empirePlanetIDs) for pid in empirePlanetIDs: canFocus= planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0 itarget=planetMap[pid].currentMeterValue(fo.meterType.targetIndustry) rtarget=planetMap[pid].currentMeterValue(fo.meterType.targetResearch) newTargets.setdefault(pid, {}).setdefault(RFocus, (0, 0)) newTargets[pid][RFocus] = ( itarget, rtarget ) if canFocus and currentFocus[pid] != RFocus: fo.issueChangeFocusOrder(pid, currentFocus[pid]) #put it back to what it was universe.updateMeterEstimates(empirePlanetIDs) return targetPP, targetRP
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 = curBestMilShipRating() unmetThreat = 0.0 currentTurn=fo.currentTurn() 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 if sysID in mySystems: threat = status.get('fleetThreat', 0) + status.get('planetThreat', 0) + 0.3* status.get('neighborThreat', 0) else: threat = status.get('fleetThreat', 0) + status.get('planetThreat', 0) + 0.1* status.get('neighborThreat', 0) unmetThreat += max( 0, threat + monsterThreat - myRating ) militaryPriority = int( 40 + max(0, 75*unmetThreat / curShipRating) ) return max( militaryPriority, 0)
def startNewGame(aggression=fo.aggression.aggressive): # pylint: disable=invalid-name "called by client at start of new game" global _timerFile, _lastTurnTimestamp, _timerBucketFile print "New game started, AI Agression level %d"% aggression # initialize AIstate global foAIstate foAIstate = AIstate.AIstate(aggression = aggression) foAIstate.sessionStartCleanup() print "Initialized foAIstate class" planet_id = PlanetUtilsAI.getCapital() planet = None universe = fo.getUniverse() if planet_id is not None and planet_id != -1: planet = universe.getPlanet(planet_id) new_name = random.choice(_capitols.get(aggression, [""]).split('\n')).strip() + " " + planet.name print "Capitol City Names are: ", _capitols print "This Capitol New name is ", new_name res = fo.issueRenameOrder(planet_id, new_name) print "Capitol Rename attempt result: %d; planet now named %s"% (res, planet.name) if _timerFile: _timerFile.close() if ResourcesAI.resourceTimerFile: ResourcesAI.resourceTimerFile.close() empire_id = fo.getEmpire().empireID try: if os.path.exists("timers") and os.path.isdir("timers"): timerpath = "timers"+os.path.sep+"timer_%02d.dat"% (empire_id-1) _timerFile = open(timerpath, 'w') _timerFile.write("Turn\t" + "\t".join(timerEntries ) +'\n') timerbucketpath = "timers"+os.path.sep+"timer_bucket_%02d.dat"% (empire_id-1) _timerBucketFile = open(timerbucketpath, 'w') _timerBucketFile.write("Turn\t" + "\t".join(_timerBucketEntries) +'\n') _lastTurnTimestamp = time() if ResourcesAI.doResourceTiming: ResourcesAI.resourceTimerFile = open("timers"+os.path.sep+"resourceTimer_%2d.dat"%(empire_id-1), 'w') ResourcesAI.resourceTimerFile.write("Turn\t"+ "\t".join(ResourcesAI.timer_entries)+"\n") print "timer file saved at " + timerpath except: _timerFile = None ResourcesAI.resourceTimerFile = None ResourcesAI.doResourceTiming = False print "Error: exception caught starting timing: ", traceback.format_exc() print "won't record timing info"
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire): "return the invasion value of a planet" #TODO: add more factors, as used for colonization universe = fo.getUniverse() empireID = empire.empireID distanceFactor = 0 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 capitalID = PlanetUtilsAI.getCapital() homeworld = universe.getPlanet(capitalID) if homeworld: homeSystemID = homeworld.systemID evalSystemID = planet.systemID leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID)) distanceFactor = 4.0/(leastJumpsPath + 1) troops = planet.currentMeterValue(fo.meterType.troops) specName=planet.speciesName species=fo.getSpecies(specName) if not species:# perhaps stealth might make species info inaccessible targetPop=planet.currentMeterValue(fo.meterType.targetPopulation) if planetID in fleetSupplyablePlanetIDs: popVal = 4*targetPop else: popVal = 6*targetPop#assign higher value if the colony would extend our supply range planetSpecials = list(planet.specials) specialVal=0 if ( ( planet.size == fo.planetSize.asteroids ) and (empire.getTechStatus("PRO_ASTEROID_MINE") == fo.techStatus.complete ) ): specialVal= 15 # asteroid mining is great, fast return for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : if special in planetSpecials: specialVal = 40 return popVal+specialVal, troops else: popVal = evaluatePlanet(planetID, AIFleetMissionType.FLEET_MISSION_COLONISATION, [planetID], species, empire) #evaluatePlanet is implorted from ColonisationAI if planetID not in fleetSupplyablePlanetIDs: popVal = 2.0*popVal#assign higher value if the colony would extend our supply range return popVal, troops
def startNewGame(aggression=fo.aggression.aggressive): global __timerFile, lastTurnTimestamp, __timerBucketFile print "New game started, AI Agression level %d"%aggression # initialize AIstate global foAIstate foAIstate = AIstate.AIstate(aggression=aggression) foAIstate.sessionStartCleanup() print "Initialized foAIstate class" planetID = PlanetUtilsAI.getCapital() planet=None universe=fo.getUniverse() if planetID is not None: planet = universe.getPlanet(planetID) fo.issueRenameOrder(planetID, capitols.get(aggression, "")+planet.name) if __timerFile: __timerFile.close() if ResourcesAI.resourceTimerFile: ResourcesAI.resourceTimerFile.close() empireID = fo.getEmpire().empireID try: if os.path.exists("timers") and os.path.isdir("timers"): timerpath="timers"+os.path.sep+"timer_%02d.dat"%(empireID-1) __timerFile = open(timerpath, 'w') __timerFile.write("Turn\t" + "\t".join(__timerEntries) +'\n') timerBucketpath="timers"+os.path.sep+"timer_bucket_%02d.dat"%(empireID-1) __timerBucketFile = open(timerBucketpath, 'w') __timerBucketFile.write("Turn\t" + "\t".join(__timerBucketEntries) +'\n') lastTurnTimestamp = time() if ResourcesAI.doResourceTiming: ResourcesAI.resourceTimerFile = open("timers"+os.path.sep+"resourceTimer_%2d.dat"%(empireID-1), 'w') ResourcesAI.resourceTimerFile.write("Turn\t"+ "\t".join(ResourcesAI.__timerEntries)+"\n") print "timer file saved at "+timerpath except: __timerFile=None ResourcesAI.resourceTimerFile =None ResourcesAI.doResourceTiming = False print "Error: exception caught starting timing: ", traceback.format_exc() print "won't record timing info"
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 getMilitaryFleets(tryReset=True): "get armed military fleets" global MilitaryAllocations, totMilRating universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() if capitalID == None: homeworld=None else: homeworld = universe.getPlanet(capitalID) if homeworld: homeSystemID = homeworld.systemID else: homeSystemID=-1 allMilitaryFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_MILITARY ) if tryReset and ((fo.currentTurn()+empireID) % 10 ==0): tryAgain(allMilitaryFleetIDs) totMilRating = sum( map(lambda x: foAI.foAIstate.getRating(x).get('overall', 0), allMilitaryFleetIDs ) ) milShips = 0 for fid in allMilitaryFleetIDs: milShips += foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) print "==================================================" print "Total Military Rating: %d"%totMilRating print "---------------------------------" foAI.foAIstate.militaryRating=totMilRating milFleetIDs = list( FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allMilitaryFleetIDs)) availMilRating = sum( map(lambda x: foAI.foAIstate.getRating(x).get('overall', 0), milFleetIDs ) ) print "==================================================" print "Available Military Rating: %d"%availMilRating print "---------------------------------" remainingMilRating = availMilRating allocations = [] if milFleetIDs == []: MilitaryAllocations = [] return alreadyAssignedRating={} for sysID in universe.systemIDs: alreadyAssignedRating[sysID]=0 for fleetID in [fid for fid in allMilitaryFleetIDs if fid not in milFleetIDs]: aiFleetMission = foAI.foAIstate.getAIFleetMission(fleetID) sysTargets= [] for aiFleetMissionType in aiFleetMission.getAIMissionTypes(): aiTargets = aiFleetMission.getAITargets(aiFleetMissionType) for aiTarget in aiTargets: sysTargets.extend(aiTarget.getRequiredSystemAITargets()) if not sysTargets: #shouldn't really be possible continue lastSys = sysTargets[-1].getTargetID() # will count this fleet as assigned to last system in target list alreadyAssignedRating[lastSys] += foAI.foAIstate.getRating(fleetID).get('overall', 0) #TODO: would preferably tally attack and health and take product # get systems to defend capitalID = PlanetUtilsAI.getCapital() if capitalID != None: capitalPlanet = universe.getPlanet(capitalID) else: capitalPlanet=None #TODO: if no owned planets try to capture one! if capitalPlanet: capitalSysID = capitalPlanet.systemID else: # should be rare, but so as to not break code below, pick a randomish mil-centroid system systemDict = {} for fleetID in allMilitaryFleetIDs: status = foAI.foAIstate.fleetStatus.get(fleetID, None) if status is not None: sysID = status['sysID'] if len( list( universe.getSystem(sysID).planetIDs ) ) ==0: continue systemDict[sysID] = systemDict.get( sysID, 0) + status.get('rating', {}).get('overall', 0) rankedSystems = sorted( [(val, sysID) for sysID, val in systemDict.items() ] ) if rankedSystems: capitalSysID = rankedSystems[-1][-1] else: capitalSysID = foAI.foAIstate.fleetStatus.items()[0]['sysID'] if fo.currentTurn() < 20: threatBias = 0 elif fo.currentTurn() < 40: threatBias = 10 elif fo.currentTurn() < 60: threatBias = 80 elif fo.currentTurn() < 80: threatBias = 200 else: threatBias = 400 threatBias = 0 safetyFactor = [ 4.0, 3.0, 1.5, 1.0, 1.0, 0.95 ][foAI.foAIstate.aggression] topTargetPlanets = [pid for pid, pscore, trp in AIstate.invasionTargets[:PriorityAI.allottedInvasionTargets] if pscore > 20] + [pid for pid, pscore in foAI.foAIstate.colonisablePlanetIDs[:10] if pscore > 20] topTargetSystems = [] for sysID in PlanetUtilsAI.getSystems( topTargetPlanets ): if sysID not in topTargetSystems: topTargetSystems.append(sysID) #doing this rather than set, to preserve order # allocation format: ( sysID, newAllocation, takeAny, maxMultiplier ) #================================ #--------Capital Threat ---------- capitalThreat = safetyFactor*(2* threatBias +sum( [ foAI.foAIstate.systemStatus[capitalSysID][thrtKey] for thrtKey in [tkey for tkey in foAI.foAIstate.systemStatus.get(capitalSysID, {}).keys() if 'Threat' in tkey]] )) newAlloc=0 if tryReset: if (capitalThreat > 0.5*(availMilRating+0.8*alreadyAssignedRating[capitalSysID]) ) : tryAgain(allMilitaryFleetIDs) return if capitalThreat > 0.8*alreadyAssignedRating[capitalSysID]: newAlloc = min(remainingMilRating, int( 0.999 + 1.2*(capitalThreat- 0.8*alreadyAssignedRating[capitalSysID]) ) ) allocations.append( ( capitalSysID, newAlloc, True, 3) ) remainingMilRating -= newAlloc print "Empire Capital System: (%d) %s -- threat : %d, military allocation: existing: %d ; new: %d"%(capitalSysID, universe.getSystem(capitalSysID).name , capitalThreat, alreadyAssignedRating[capitalSysID], newAlloc) print "-----------------" #================================ #--------Empire Occupied Systems ---------- empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) empireOccupiedSystemIDs = list( set(PlanetUtilsAI.getSystems(empirePlanetIDs)) - set([capitalSysID] ) ) print "Empire-Occupied Systems: %s"%( [ "| %d %s |"%(eoSysID, universe.getSystem(eoSysID).name) for eoSysID in empireOccupiedSystemIDs ] ) print "-----------------" if len( empireOccupiedSystemIDs ) > 0: ocSysTotThreat = [ ( oSID, threatBias +safetyFactor*sum( [ foAI.foAIstate.systemStatus.get(oSID, {}).get(thrtKey, 0) for thrtKey in ['fleetThreat', 'monsterThreat','planetThreat', 'neighborThreat']] ) ) for oSID in empireOccupiedSystemIDs ] totocSysThreat = sum( [thrt for sid, thrt in ocSysTotThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in ocSysTotThreat] ) allocationFactor = min( 1.2, remainingMilRating /max(0.01, ( totocSysThreat -totCurAlloc) )) ocSysAlloc = 0 for sid, thrt in ocSysTotThreat: curAlloc=0.8*alreadyAssignedRating[sid] if (thrt > 0.8*(remainingMilRating+curAlloc )) and tryReset: tryAgain(allMilitaryFleetIDs) return thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 0: thisAlloc = max(0, min( min( int(0.99999 + (thrt-curAlloc)*allocationFactor ), 0.5*availMilRating) , remainingMilRating)) allocations.append( (sid, thisAlloc, True, 2) ) remainingMilRating -= thisAlloc ocSysAlloc += thisAlloc print "Provincial Empire-Occupied Sytems under total threat: %d -- total mil allocation: existing %d ; new: %d"%(totocSysThreat, totCurAlloc, ocSysAlloc ) print "-----------------" #================================ #--------Top Targeted Systems ---------- #TODO: do native invasions highest priority otherTargetedSystemIDs = topTargetSystems print "Top Colony and Invasion Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" # for these, calc local threat only, no neighbor threat, but use a multiplier for fleet safety if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0)) ) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if 2*thrt>curAlloc and (curAlloc>0 or remainingMilRating > (10+ (2*thrt-curAlloc))): #only record more allocation for this invasion if we already started or have enough rating available thisAlloc =int(10.99999 + (1.5*thrt-curAlloc)) takeAny= curAlloc>0 allocations.append( (sid, thisAlloc, takeAny ,4) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Top Colony and Invasion Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" #================================ #--------Targeted Systems ---------- #TODO: do native invasions highest priority otherTargetedSystemIDs = [sysID for sysID in AIstate.invasionTargetedSystemIDs if sysID not in topTargetSystems] print "Other Invasion Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" # for these, calc local threat only, no neighbor threat, but use a multiplier for fleet safety if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, max(10, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0)) ) ) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if thrt>curAlloc and remainingMilRating > 10+ 1.5*(thrt-curAlloc) : #only record an allocation for this invasion if we have enough rating available thisAlloc =int(10.99999 + (thrt-curAlloc)*1.5) allocations.append( (sid, thisAlloc, False, 3) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Invasion Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" otherTargetedSystemIDs = [sysID for sysID in list(set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs)) if sysID not in topTargetSystems] print "Other Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" # for these, calc local threat only, no neighbor threat, but use a multiplier for fleet safety if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, safetyFactor*(threatBias +foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0) )) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 1.5*(thrt-curAlloc): thisAlloc = min( min( int(0.99999 + (thrt-curAlloc)*1.5), remainingMilRating ), 0.5*availMilRating) allocations.append( (sid, thisAlloc, False, 2.0) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Other Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" otherTargetedSystemIDs = [] fleetSuppliableSystemIDs = empire.fleetSupplyableSystemIDs for sysID in AIstate.opponentSystemIDs: if sysID in fleetSuppliableSystemIDs: otherTargetedSystemIDs.append(sysID) else: for nID in universe.getImmediateNeighbors(sysID, empireID): if nID in fleetSuppliableSystemIDs: otherTargetedSystemIDs.append(sysID) break print "Blockade Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" # for these, calc local threat only, no neighbor threat, but use a multiplier for fleet safety if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0) )) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 1.5*(thrt-curAlloc): thisAlloc = min( min( int(0.99999 + (thrt-curAlloc)*1.5), remainingMilRating ), 0.5*availMilRating) allocations.append( (sid, thisAlloc, False, 10) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Blockade Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Blockade Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" currentMilSystems = [sid for sid, alloc, takeAny, mm in allocations ] interiorIDs = list( foAI.foAIstate.expInteriorSystemIDs) interiorTargets1 = [sid for sid in interiorIDs if ( ( sid not in currentMilSystems )) ] interiorTargets = [sid for sid in interiorIDs if ( (threatBias + foAI.foAIstate.systemStatus.get(sid, {}).get('fleetThreat', 0) >0.8*alreadyAssignedRating[sid] ) ) ] print "" print "Other Empire-Interior Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in interiorTargets1 ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety if len(interiorTargets) >0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)) ) for oSID in interiorTargets ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 0 : thisAlloc = min( min( int(0.99999 +( thrt-curAlloc)*1.5), remainingMilRating ), 0.5*availMilRating) allocations.append( (sid, thisAlloc, True, 1.2) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Other interior system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Other Interior Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" else: print "-----------------" print "No Other Interior Systems with fleet threat " print "-----------------" monsterDens=[] exploTargetIDs, _ = ExplorationAI.getCurrentExplorationInfo(verbose=False) print "" print "Exploration-targeted Systems: %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in exploTargetIDs ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety if len(exploTargetIDs) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0) )) for oSID in exploTargetIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) if availMilRating <1125: maxMilRating = availMilRating else: maxMilRating = 0.5*availMilRating for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 0: if foAI.foAIstate.systemStatus.get(sid, {}).get('monsterThreat', 0) > 2000: monsterDens.append(sid) continue # consider dealing with big monsters later thisAlloc = min( min( int(0.99999 + (thrt-curAlloc)*1.5), remainingMilRating ), 0.5*availMilRating) allocations.append( (sid, thisAlloc, False, 2) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Exploration-targeted %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Exploration-targeted s under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if universe.systemsConnected(sysID, homeSystemID, empireID) ] currentMilSystems = [sid for sid, alloc, takeAny, multiplier in allocations if alloc > 0 ] borderTargets1 = [sid for sid in accessibleSystemIDs if ( ( sid not in currentMilSystems )) ] borderTargets = [sid for sid in borderTargets1 if ( ( threatBias +foAI.foAIstate.systemStatus.get(sid, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(sid, {}).get('planetThreat', 0) > 0.8*alreadyAssignedRating[sid] )) ] print "" print "Empire-Accessible Systems not yet allocated military: %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID) and universe.getSystem(sysID).name) for sysID in borderTargets1 ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety if len(borderTargets) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0)) ) for oSID in borderTargets ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 0: if foAI.foAIstate.systemStatus.get(sid, {}).get('monsterThreat', 0) > 2000: if sid not in monsterDens: monsterDens.append(sid) continue # consider dealing with big monsters later thisAlloc = min( min( int(0.99999 + (thrt-curAlloc)*1.5), remainingMilRating ), 0.5*availMilRating) allocations.append( (sid, thisAlloc, False, 5) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Other Empire-Accessible system %4d ( %10s ) has local biased threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" print "Other Empire-Accessible Systems under total biased threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" else: print "-----------------" print "No Other Empire-Accessible Systems with biased local threat " print "-----------------" print "" print "Big-Monster Dens: %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in monsterDens ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety if len(monsterDens) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0)+foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0) ) ) for oSID in monsterDens ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 2* thrt: thisAlloc = int(0.99999 + (thrt-curAlloc)*1.5) allocations.append( (sid, thisAlloc, False, 5) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc print "Monster Den %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) print "-----------------" if remainingMilRating <=6: newAllocations = [ (sid, alc, alc, ta) for (sid, alc, ta, mm) in allocations ] else: try: totAlloc = sum( [alloc for sid, alloc, takeAny, maxMul in allocations ] ) except: print "error unpacking sid, alloc, takeAny, maxMul from ", allocations factor =(2.0* remainingMilRating ) / ( totAlloc + 0.1) print "Remaining military strength allocation %d will be allocated as %.1f %% surplus allocation to top current priorities"%(remainingMilRating, 100*factor) newAllocations = [] for sid, alloc, takeAny, maxMul in allocations: if remainingMilRating <= 0 : newAllocations.append( ( sid, alloc, alloc, takeAny ) ) else: thisAlloc = int( max( maxMul-1, factor )* alloc ) newAllocations.append( ( sid, alloc+thisAlloc, alloc, takeAny ) ) remainingMilRating -= thisAlloc MilitaryAllocations = newAllocations minMilAllocations = dict( [ (sid, alloc) for sid, alloc, takeAny, mm in allocations ] ) print "------------------------------\nFinal Military Allocations: %s \n-----------------------"%dict( [ (sid, alloc) for sid, alloc, minalloc, takeAny in newAllocations ] ) # export military systems for other AI modules AIstate.militarySystemIDs = [sid for sid, alloc, minalloc, takeAny in newAllocations]
def evaluatePlanet(planetID, missionType, fleetSupplyablePlanetIDs, species, empire, detail = []): "returns the colonisation value of a planet" # TODO: in planet evaluation consider specials and distance if detail != []: detail = [] discountMultiplier = 20.0 priorityScaling=1.0 maxGGGs=1 if empire.productionPoints <100: backupFactor = 0.0 else: backupFactor = min(1.0, (empire.productionPoints/200.0)**2 ) universe = fo.getUniverse() claimedStars= foAI.foAIstate.misc.get('claimedStars', {} ) if claimedStars == {}: for sType in AIstate.empireStars: claimedStars[sType] = list( AIstate.empireStars[sType] ) for sysID in set( AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs): tSys = universe.getSystem(sysID) if not tSys: continue claimedStars.setdefault( tSys.starType, []).append(sysID) empireResearchList = [element.tech for element in empire.researchQueue] planet = universe.getPlanet(planetID) if (planet == None): VisMap = dictFromMap(universe.getVisibilityTurnsMap(planetID, empire.empireID)) print "Planet %d object not available; visMap: %s"%(planetID, VisMap) return 0 detail.append("%s : "%planet.name ) system = universe.getSystem(planet.systemID) tagList=[] starBonus=0 colonyStarBonus=0 researchBonus=0 growthVal = 0 fixedInd = 0 fixedRes = 0 haveExistingPresence=False if AIstate.colonizedSystems.get(planet.systemID, [planetID]) != [planetID]: #if existing presence is target planet, don't count haveExistingPresence=True if species: tagList = list( species.tags ) starPopMod=0 if system: alreadyGotThisOne= planet.systemID in (AIstate.popCtrSystemIDs + AIstate.outpostSystemIDs) if "PHOTOTROPHIC" in tagList: starPopMod = photoMap.get( system.starType, 0 ) detail.append( "PHOTOTROPHIC popMod %.1f"%starPopMod ) 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 (claimedStars.get(fo.starType.blue, [])+claimedStars.get(fo.starType.white, []))==0: starBonus +=20* discountMultiplier detail.append( "PRO_SOL_ORB_GEN BW %.1f"%(20* discountMultiplier) ) elif not alreadyGotThisOne: starBonus +=10*discountMultiplier*backupFactor #still has extra value as an alternate location for solar generators detail.append( "PRO_SOL_ORB_GEN BW Backup Location %.1f"%(10* discountMultiplier *backupFactor) ) elif fo.currentTurn() > 100: #lock up this whole system pass #starBonus += 5 #TODO: how much? #detail.append( "PRO_SOL_ORB_GEN BW LockingDownSystem %.1f"%5 ) if system.starType in [fo.starType.yellow, fo.starType.orange]: if len ( claimedStars.get(fo.starType.blue, [])+claimedStars.get(fo.starType.white, [])+ claimedStars.get(fo.starType.yellow, [])+claimedStars.get(fo.starType.orange, []))==0: starBonus +=10* discountMultiplier detail.append( "PRO_SOL_ORB_GEN YO %.1f"%(10* discountMultiplier )) else: pass #starBonus +=2 #still has extra value as an alternate location for solar generators #detail.append( "PRO_SOL_ORB_GEN YO Backup %.1f"%2 ) if system.starType in [fo.starType.blackHole] and fo.currentTurn() > 100: if not alreadyGotThisOne: starBonus +=10*discountMultiplier*backupFactor #whether have tech yet or not, assign some base value detail.append( "Black Hole %.1f"%(10* discountMultiplier*backupFactor) ) else: starBonus += 5*discountMultiplier*backupFactor detail.append( "Black Hole Backup %.1f"%(5* discountMultiplier*backupFactor ) ) 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 (claimedStars.get(fo.starType.blackHole, []))==0: starBonus +=200*discountMultiplier #pretty rare planets, good for generator detail.append( "PRO_SINGULAR_GEN %.1f"%(200* discountMultiplier ) ) elif planet.systemID not in claimedStars.get(fo.starType.blackHole, []): starBonus +=100*discountMultiplier*backupFactor #still has extra value as an alternate location for generators & for blocking enemies generators detail.append( "PRO_SINGULAR_GEN Backup %.1f"%(100* discountMultiplier*backupFactor ) ) elif system.starType in [fo.starType.red] and ( len (claimedStars.get(fo.starType.blackHole, [])) )==0: rfactor = (1.0+len (claimedStars.get(fo.starType.red, [])))**(-2) starBonus +=40*discountMultiplier*backupFactor*rfactor # can be used for artificial black hole detail.append( "Red Star for Art Black Hole %.1f"%(20* discountMultiplier*backupFactor*rfactor ) ) 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 (claimedStars.get(fo.starType.neutron, []))==0: starBonus +=80*discountMultiplier #pretty rare planets, good for armor detail.append( "PRO_NEUTRONIUM_EXTRACTION %.1f"%(80* discountMultiplier ) ) else: starBonus +=20*discountMultiplier*backupFactor #still has extra value as an alternate location for generators & for bnlocking enemies generators detail.append( "PRO_NEUTRONIUM_EXTRACTION Backup %.1f"%(20* discountMultiplier*backupFactor ) ) if (empire.getTechStatus("SHP_ENRG_BOUND_MAN") == fo.techStatus.complete) or ( "SHP_ENRG_BOUND_MAN" in empireResearchList[:6]) : if system.starType in [fo.starType.blackHole, fo.starType.blue] : if len (claimedStars.get(fo.starType.blackHole, []) + claimedStars.get(fo.starType.blue, []) ) ==0: colonyStarBonus +=100*discountMultiplier #pretty rare planets, good for generator detail.append( "SHP_ENRG_BOUND_MAN %.1f"%(100* discountMultiplier ) ) elif planet.systemID not in (claimedStars.get(fo.starType.blackHole, []) + claimedStars.get(fo.starType.blue, []) ): colonyStarBonus +=50*discountMultiplier*backupFactor #still has extra value as an alternate location for generators & for bnlocking enemies generators detail.append( "SHP_ENRG_BOUND_MAN Backup %.1f"%(50* discountMultiplier*backupFactor ) ) retval = starBonus planetSpecials = list(planet.specials) if "ECCENTRIC_ORBIT_SPECIAL" in planet.specials: fixedRes += discountMultiplier*2*3 detail.append( "ECCENTRIC_ORBIT_SPECIAL %.1f"%(discountMultiplier*2*3 ) ) if ( "ANCIENT_RUINS_SPECIAL" in planet.specials ): #TODO: add value for depleted ancient ruins retval += discountMultiplier*20 detail.append("Undepleted Ruins %.1f"%discountMultiplier*20) if (missionType == AIFleetMissionType.FLEET_MISSION_OUTPOST ): for special in planetSpecials: if "_NEST_" in special: retval+=5*discountMultiplier*backupFactor # get an outpost on the nest quick detail.append( "%s %.1f"%(special, discountMultiplier*5*backupFactor ) ) if ( ( planet.size == fo.planetSize.asteroids ) and (empire.getTechStatus("PRO_MICROGRAV_MAN") == fo.techStatus.complete )): if system: astVal=0 for pid in system.planetIDs: otherPlanet=universe.getPlanet(pid) if otherPlanet.size == fo.planetSize.asteroids: if pid==planetID: continue elif pid < planetID: astVal=0 break elif otherPlanet.size!= fo.planetSize.gasGiant and otherPlanet.owner==empire.empireID: astVal+=5 * discountMultiplier retval += astVal if astVal >0: detail.append( "Asteroids %.1f"%(discountMultiplier*20 ) ) if ( ( planet.size == fo.planetSize.gasGiant ) and ( (empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete ) or ( "PRO_ORBITAL_GEN" in empireResearchList[:3]) )): if system: GGList=[] orbGenVal=0 GGDetail=[] for pid in system.planetIDs: otherPlanet=universe.getPlanet(pid) if otherPlanet.size== fo.planetSize.gasGiant: GGList.append(pid) if pid!=planetID and otherPlanet.owner==empire.empireID and (AIFocusType.FOCUS_INDUSTRY in list(otherPlanet.availableFoci)+[otherPlanet.focus]): orbGenVal+=2*10*discountMultiplier GGDetail.append( "GGG for %s %.1f"%(otherPlanet.name, discountMultiplier*10 ) ) if planetID in sorted(GGList)[:maxGGGs]: retval += orbGenVal detail.extend( GGDetail ) else: detail.append( "Won't GGG") thrtFactor = 1.0 if ( foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('monsterThreat', 0) )> 2*curBestMilShipRating: thrtFactor = 0.5 retval *=thrtFactor detail.append( "threat reducing value" ) if haveExistingPresence: detail.append("multiplanet presence") if thrtFactor < 1.0: retval = (retval/thrtFactor) * (0.5 + 0.5*thrtFactor) #mitigate threat retval *=1.5 return int(retval) else: #colonization mission if not species: return 0 retval += fixedRes retval += colonyStarBonus asteroidBonus=0 gasGiantBonus=0 GGPresent=False miningBonus=0 perGGG=2*10*discountMultiplier planetSize = planet.size if system and AIFocusType.FOCUS_INDUSTRY in species.foci: for pid in [id for id in system.planetIDs if id != planetID]: p2 = universe.getPlanet(pid) if p2: if p2.size== fo.planetSize.asteroids : if ( (empire.getTechStatus("PRO_MICROGRAV_MAN") == fo.techStatus.complete ) or ( "PRO_MICROGRAV_MAN" in empireResearchList[:3]) ): asteroidBonus = 2*5*discountMultiplier detail.append( "Asteroid mining from %s %.1f"%(p2.name, 2*discountMultiplier*5 ) ) if p2.size== fo.planetSize.gasGiant : GGPresent=True if ( (empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete ) or ( "PRO_ORBITAL_GEN" in empireResearchList[:3]) ): gasGiantBonus += perGGG detail.append( "GGG from %s %.1f"%(p2.name, perGGG ) ) gasGiantBonus = min( gasGiantBonus, maxGGGs * perGGG ) if (planet.size==fo.planetSize.gasGiant): if not (species and species.name == "SP_SUPER_TEST"): detail.append("Can't Settle GG" ) return 0 else: planetEnv = fo.planetEnvironment.adequate#I think planetSize=6 #I think elif ( planet.size == fo.planetSize.asteroids ): planetSize=3 #I think if not species or (species.name not in [ "SP_EXOBOT", "SP_SUPER_TEST" ]): detail.append( "Can't settle Asteroids" ) return 0 elif species.name == "SP_EXOBOT": planetEnv =fo.planetEnvironment.poor elif species.name == "SP_SUPER_TEST": planetEnv = fo.planetEnvironment.adequate#I think else: return 0 else: planetEnv = environs[ str(species.getPlanetEnvironment(planet.type)) ] if planetEnv==0: return -9999 popSizeMod=0 conditionalPopSizeMod=0 popSizeMod += popSizeModMap["env"][planetEnv] detail.append("EnvironPopSizeMod(%d)"%popSizeMod) if "SELF_SUSTAINING" in tagList: popSizeMod*=2 detail.append("SelfSustaining_PSM(2)" ) if "PHOTOTROPHIC" in tagList: popSizeMod += starPopMod detail.append("Phototropic Star Bonus_PSM(%0.1f)"%starPopMod) if (empire.getTechStatus("GRO_SUBTER_HAB") == fo.techStatus.complete) or "TUNNELS_SPECIAL" in planetSpecials: if "TECTONIC_INSTABILITY_SPECIAL" not in planetSpecials: conditionalPopSizeMod += popSizeModMap["subHab"][planetEnv] if "TUNNELS_SPECIAL" in planetSpecials: T_reason="Tunnels_PSM(%d)" else: T_reason="Sub_Hab_PSM(%d)" detail.append(T_reason%popSizeModMap["subHab"][planetEnv]) for gTech, gKey in [ ("GRO_SYMBIOTIC_BIO", "symBio"), ("GRO_XENO_GENETICS", "xenoGen"), ("GRO_XENO_HYBRID", "xenoHyb"), ("GRO_CYBORG", "cyborg"), ("CON_NDIM_STRUC", "ndim"), ("CON_ORBITAL_HAB", "orbit") ]: if empire.getTechStatus(gTech) == fo.techStatus.complete: popSizeMod += popSizeModMap[gKey][planetEnv] detail.append("%s_PSM(%d)"%(gKey, popSizeModMap[gKey][planetEnv])) if "GAIA_SPECIAL" in planet.specials: popSizeMod += 3 detail.append("Gaia_PSM(3)") for special in [ "SLOW_ROTATION_SPECIAL", "SOLID_CORE_SPECIAL"] : if special in planetSpecials: popSizeMod -= 1 detail.append("%s_PSM(-1)"%special) applicableBoosts=set([]) for thisTag in [ tag for tag in tagList if tag in AIDependencies.metabolims]: metabBoosts= AIDependencies.metabolimBoostMap.get(thisTag, []) if popSizeMod > 0: for key in activeGrowthSpecials.keys(): if ( len(activeGrowthSpecials[key])>0 ) and ( key in metabBoosts ): applicableBoosts.add(key) detail.append("%s boost active"%key) for boost in metabBoosts: if boost in planetSpecials: applicableBoosts.add(boost) detail.append("%s boost present"%boost) nBoosts = len(applicableBoosts) if nBoosts: popSizeMod += nBoosts detail.append("boosts_PSM(%d from %s)"%(nBoosts, applicableBoosts)) if popSizeMod > 0: popSizeMod += conditionalPopSizeMod popSize = planetSize * popSizeMod detail.append("baseMaxPop size*psm %d * %d = %d"%(planetSize, popSizeMod, popSize) ) if "DIM_RIFT_MASTER_SPECIAL" in planet.specials: popSize -= 4 detail.append("DIM_RIFT_MASTER_SPECIAL(maxPop-4)") detail.append("maxPop %.1f"%popSize) for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : if special in planetSpecials: miningBonus+=1 proSingVal = [0, 4][(len( claimedStars.get(fo.starType.blackHole, [])) > 0)] basePopInd=0.2 indMult=1 indTechMap={ "GRO_ENERGY_META": 0.5, "PRO_ROBOTIC_PROD":0.4, "PRO_FUSION_GEN": 1.0, "PRO_INDUSTRY_CENTER_I": 1, "PRO_INDUSTRY_CENTER_II":1, "PRO_INDUSTRY_CENTER_III":1, "PRO_SOL_ORB_GEN": 2.0, #assumes will build a gen at a blue/white star "PRO_SINGULAR_GEN": proSingVal, } for tech in indTechMap: if (empire.getTechStatus(tech) == fo.techStatus.complete): indMult += indTechMap[tech] indVal = 0 if (empire.getTechStatus("PRO_SENTIENT_AUTOMATION") == fo.techStatus.complete): fixedInd += discountMultiplier * 5 if AIFocusType.FOCUS_INDUSTRY in species.foci: indVal += discountMultiplier * basePopInd * popSize*miningBonus indVal += discountMultiplier * basePopInd * popSize * indMult detail.append("indVal %.1f"%indVal) # used to 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 for special in [ spec for spec in planetSpecials if spec in AIDependencies.metabolimBoosts]: gbonus = discountMultiplier * basePopInd * indMult * empireMetabolisms.get( AIDependencies.metabolimBoosts[special] , 0)# due to growth applicability to other planets growthVal += gbonus detail.append( "Bonus for %s: %.1f"%(special, gbonus)) basePopRes = 0.2 #will also be doubling value of research, below if AIFocusType.FOCUS_RESEARCH in species.foci: researchBonus += discountMultiplier*2*basePopRes*popSize if ( "ANCIENT_RUINS_SPECIAL" in planet.specials ) or ( "ANCIENT_RUINS_DEPLETED_SPECIAL" in planet.specials ): researchBonus += discountMultiplier*2*basePopRes*popSize*5 detail.append("Ruins Research") if "COMPUTRONIUM_SPECIAL" in planet.specials: researchBonus += discountMultiplier*2*10 #TODO: do actual calc detail.append("COMPUTRONIUM_SPECIAL") if popSize <= 0: detail.append("Non-positive population projection for species '%s', so no colonization value"%(species and species.name)) return 0 retval += max(indVal+asteroidBonus+gasGiantBonus, researchBonus, growthVal)+fixedInd + fixedRes if planet.systemID in annexableRing1: retval += 10 elif planet.systemID in annexableRing2: retval += 20 elif planet.systemID in annexableRing3: retval += 10 retval *= priorityScaling thrtRatio = (foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0)+foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('monsterThreat', 0)+0.2*foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('neighborThreat', 0)) / float(curBestMilShipRating) if False: if thrtRatio > 4: retval = 0.3*retval elif thrtRatio >= 2: retval = 0.7* retval elif thrtRatio > 0: retval = 0.85* retval thrtFactor = 1.0 if thrtRatio > 1: detail.append("threat reducing value") thrtFactor = 0.85 retval *= thrtFactor if haveExistingPresence: detail.append("multiplanet presence") if thrtFactor < 1.0: retval = (retval/thrtFactor) * (0.5 + 0.5*thrtFactor) #mitigate threat retval *=1.5 return retval
def getMilitaryFleets(milFleetIDs=None, tryReset=True, round="Main"): "get armed military fleets" global MilitaryAllocations, totMilRating universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID capitalID = PlanetUtilsAI.getCapital() if capitalID == None: homeworld=None else: homeworld = universe.getPlanet(capitalID) if homeworld: homeSystemID = homeworld.systemID else: homeSystemID=-1 if milFleetIDs !=None: allMilitaryFleetIDs = milFleetIDs else: allMilitaryFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_MILITARY ) if tryReset and ((fo.currentTurn()+empireID) % 10 ==0) and round=="Main": tryAgain(allMilitaryFleetIDs, tryReset=False, round = round+" Reset") milShips = 0 for fid in allMilitaryFleetIDs: milShips += foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) thisTotMilRating = sum( map(lambda x: foAI.foAIstate.getRating(x).get('overall', 0), allMilitaryFleetIDs ) ) if "Main" in round: totMilRating = thisTotMilRating print "==================================================" print "%s Round Total Military Rating: %d"%(round, totMilRating) print "---------------------------------" foAI.foAIstate.militaryRating=totMilRating milFleetIDs = list( FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allMilitaryFleetIDs)) availMilRating = sum( map(lambda x: foAI.foAIstate.getRating(x).get('overall', 0), milFleetIDs ) ) if "Main" in round: print "==================================================" print "%s Round Available Military Rating: %d"%(round, availMilRating) print "---------------------------------" remainingMilRating = availMilRating allocations = [] allocationGroups={} if milFleetIDs == []: if "Main" in round: MilitaryAllocations = [] return [] #for each system, get total rating of fleets assigned to it alreadyAssignedRating={} assignedAttack={} assignedHP={} for sysID in universe.systemIDs: assignedAttack[sysID]=0 assignedHP[sysID]=0 for fleetID in [fid for fid in allMilitaryFleetIDs if fid not in milFleetIDs]: aiFleetMission = foAI.foAIstate.getAIFleetMission(fleetID) sysTargets= [] for aiFleetMissionType in aiFleetMission.getAIMissionTypes(): aiTargets = aiFleetMission.getAITargets(aiFleetMissionType) for aiTarget in aiTargets: sysTargets.extend(aiTarget.getRequiredSystemAITargets()) if not sysTargets: #shouldn't really be possible continue lastSys = sysTargets[-1].getTargetID() # will count this fleet as assigned to last system in target list assignedAttack[lastSys] += foAI.foAIstate.getRating(fleetID).get('attack', 0) assignedHP[lastSys] += foAI.foAIstate.getRating(fleetID).get('health', 0) for sysID in universe.systemIDs: mydefenses = foAI.foAIstate.systemStatus.get(sysID, {}).get( 'mydefenses', {} ) mypattack = mydefenses.get('attack', 0) myphealth = mydefenses.get('health', 0) alreadyAssignedRating[sysID] = ( assignedAttack[sysID] + mypattack ) * ( assignedHP[sysID] + myphealth ) # get systems to defend capitalID = PlanetUtilsAI.getCapital() if capitalID != None: capitalPlanet = universe.getPlanet(capitalID) else: capitalPlanet=None #TODO: if no owned planets try to capture one! if capitalPlanet: capitalSysID = capitalPlanet.systemID else: # should be rare, but so as to not break code below, pick a randomish mil-centroid system capitalSysID=None #unless we can find one to use systemDict = {} for fleetID in allMilitaryFleetIDs: status = foAI.foAIstate.fleetStatus.get(fleetID, None) if status is not None: sysID = status['sysID'] if len( list( universe.getSystem(sysID).planetIDs ) ) ==0: continue systemDict[sysID] = systemDict.get( sysID, 0) + status.get('rating', {}).get('overall', 0) rankedSystems = sorted( [(val, sysID) for sysID, val in systemDict.items() ] ) if rankedSystems: capitalSysID = rankedSystems[-1][-1] else: try: capitalSysID = foAI.foAIstate.fleetStatus.items()[0][1]['sysID'] except: pass if False: if fo.currentTurn() < 20: threatBias = 0 elif fo.currentTurn() < 40: threatBias = 10 elif fo.currentTurn() < 60: threatBias = 80 elif fo.currentTurn() < 80: threatBias = 200 else: threatBias = 400 else: threatBias = 0 safetyFactor = [ 4.0, 3.0, 1.5, 1.0, 1.0, 0.95 ][foAI.foAIstate.aggression] topTargetPlanets = [pid for pid, pscore, trp in AIstate.invasionTargets[:PriorityAI.allottedInvasionTargets] if pscore > 20] + [pid for pid, pscore in foAI.foAIstate.colonisablePlanetIDs[:10] if pscore > 20] topTargetSystems = [] for sysID in AIstate.invasionTargetedSystemIDs + PlanetUtilsAI.getSystems( topTargetPlanets ): if sysID not in topTargetSystems: topTargetSystems.append(sysID) #doing this rather than set, to preserve order # allocation format: ( sysID, newAllocation, takeAny, maxMultiplier ) #================================ #--------Capital Threat ---------- capitalThreat = safetyFactor*(2* threatBias +sum( [ foAI.foAIstate.systemStatus[capitalSysID][thrtKey] for thrtKey in ['totalThreat', 'neighborThreat']] )) neededRating = ratingNeeded(1.4*capitalThreat, alreadyAssignedRating[capitalSysID]) newAlloc=0 if tryReset: if (neededRating > 0.5*availMilRating) : tryAgain(allMilitaryFleetIDs) return if neededRating > 0: newAlloc = min(remainingMilRating, neededRating ) allocations.append( ( capitalSysID, newAlloc, True, 2*capitalThreat) ) allocationGroups.setdefault('capitol', []).append( ( capitalSysID, newAlloc, True, 2*capitalThreat) ) remainingMilRating -= newAlloc if "Main" in round or newAlloc >0: print "Empire Capital System: (%d) %s -- threat : %d, military allocation: existing: %d ; new: %d"%(capitalSysID, universe.getSystem(capitalSysID).name , capitalThreat, alreadyAssignedRating[capitalSysID], newAlloc) print "-----------------" #================================ #--------Empire Occupied Systems ---------- empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) empireOccupiedSystemIDs = list( set(PlanetUtilsAI.getSystems(empirePlanetIDs)) - set([capitalSysID] ) ) if "Main" in round: print "Empire-Occupied Systems: %s"%( [ "| %d %s |"%(eoSysID, universe.getSystem(eoSysID).name) for eoSysID in empireOccupiedSystemIDs ] ) print "-----------------" newAlloc=0 if len( empireOccupiedSystemIDs ) > 0: ocSysTotThreat = [ ( oSID, threatBias +safetyFactor*sum( [ foAI.foAIstate.systemStatus.get(oSID, {}).get(thrtKey, 0) for thrtKey in ['totalThreat', 'neighborThreat']] )) for oSID in empireOccupiedSystemIDs ] totocSysThreat = sum( [thrt for sid, thrt in ocSysTotThreat] ) totCurAlloc = sum( [alreadyAssignedRating[sid] for sid, thrt in ocSysTotThreat] ) allocationFactor = min( 1.5, remainingMilRating /max(0.01, ( totocSysThreat -totCurAlloc) )) ocSysAlloc = 0 for sid, thrt in ocSysTotThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.4*thrt, curAlloc) if (neededRating > 0.8*(remainingMilRating )) and tryReset: tryAgain(allMilitaryFleetIDs) return thisAlloc=0 if ( neededRating>0 ) and remainingMilRating > 0: thisAlloc = max(0, min( neededRating, 0.5*availMilRating, remainingMilRating)) newAlloc+=thisAlloc allocations.append( (sid, thisAlloc, True, 2*thrt) ) allocationGroups.setdefault('occupied', []).append( (sid, thisAlloc, True, 2*thrt) ) remainingMilRating -= thisAlloc ocSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Provincial Occupied system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "Provincial Empire-Occupied Sytems under total threat: %d -- total mil allocation: existing %d ; new: %d"%(totocSysThreat, totCurAlloc, ocSysAlloc ) print "-----------------" #================================ #--------Top Targeted Systems ---------- #TODO: do native invasions highest priority otherTargetedSystemIDs = topTargetSystems if "Main" in round: print "Top Colony and Invasion Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" # for these, calc local threat only, no neighbor threat, but use a multiplier for fleet safety newAlloc=0 if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('totalThreat', 0)+0.5*foAI.foAIstate.systemStatus.get(oSID, {}).get('neightborThreat', 0) ) ) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.4*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= alreadyAssignedRating[sid] > 0 if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) maxAlloc = safetyFactor*3*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) newAlloc+=thisAlloc allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('topTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Top Colony and Invasion Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" #================================ #--------Targeted Systems ---------- #TODO: do native invasions highest priority otherTargetedSystemIDs = [sysID for sysID in set( PlanetUtilsAI.getSystems(AIstate.opponentPlanetIDs)) if sysID not in topTargetSystems] if "Main" in round: print "Other Invasion Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" # for these, calc local threat only, no neighbor threat, but use a multiplier for fleet safety newAlloc=0 if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('totalThreat', 0)+0.5*foAI.foAIstate.systemStatus.get(oSID, {}).get('neighborThreat', 0) ) ) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.4*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= alreadyAssignedRating[sid] > 0 if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) newAlloc+=thisAlloc maxAlloc = safetyFactor*2*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('otherTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Invasion Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" otherTargetedSystemIDs = [sysID for sysID in list(set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs)) if sysID not in topTargetSystems] if "Main" in round: print "Other Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, safetyFactor*(threatBias +foAI.foAIstate.systemStatus.get(oSID, {}).get('totalThreat', 0)+0.5*foAI.foAIstate.systemStatus.get(oSID, {}).get('neighborThreat', 0) ) ) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) newAlloc=0 for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.2*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= alreadyAssignedRating[sid] > 0 if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) newAlloc+=thisAlloc maxAlloc = safetyFactor*2*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('otherTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Other Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" otherTargetedSystemIDs = [] targetableIDs = ColonisationAI.annexableSystemIDs.union( empire.fleetSupplyableSystemIDs ) for sysID in AIstate.opponentSystemIDs: if sysID in targetableIDs: otherTargetedSystemIDs.append(sysID) else: for nID in universe.getImmediateNeighbors(sysID, empireID): if nID in targetableIDs: otherTargetedSystemIDs.append(sysID) break if "Main" in round: print "Blockade Targeted Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in otherTargetedSystemIDs ] ) print "-----------------" if len( otherTargetedSystemIDs ) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('totalThreat', 0)+ 0.5*foAI.foAIstate.systemStatus.get(oSID, {}).get('neighborThreat', 0) ) ) for oSID in otherTargetedSystemIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) newAlloc=0 for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.2*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= alreadyAssignedRating[sid] > 0 if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) newAlloc+=thisAlloc maxAlloc = safetyFactor*2*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('otherTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Blockade Targeted system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Blockade Targeted Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" currentMilSystems = [sid for sid, alloc, takeAny, mm in allocations ] interiorIDs = list( foAI.foAIstate.expInteriorSystemIDs) interiorTargets1 = (targetableIDs.union(interiorIDs)).difference( currentMilSystems ) interiorTargets = [sid for sid in interiorTargets1 if ( (threatBias + foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0) >0.8*alreadyAssignedRating[sid] ) ) ] if "Main" in round: print "" print "Other Empire-Proximal Systems : %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in interiorTargets1 ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety newAlloc=0 if len(interiorTargets) >0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('totalThreat', 0)) ) for oSID in interiorTargets ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.2*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= alreadyAssignedRating[sid] > 0 if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) newAlloc+=thisAlloc maxAlloc = safetyFactor*2*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('otherTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Other interior system %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Other Interior Systems under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" elif "Main" in round: print "-----------------" print "No Other Interior Systems with fleet threat " print "-----------------" monsterDens=[] #exploTargetIDs, _ = ExplorationAI.getCurrentExplorationInfo(verbose=False) exploTargetIDs=[] if "Main" in round: print "" print "Exploration-targeted Systems: %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in exploTargetIDs ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety newAlloc=0 if len(exploTargetIDs) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0) )) for oSID in exploTargetIDs ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) if availMilRating <1125: maxMilRating = availMilRating else: maxMilRating = 0.5*availMilRating for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.2*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= False if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) newAlloc+=thisAlloc maxAlloc = safetyFactor*2*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('exploreTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Exploration-targeted %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Exploration-targeted s under total threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if universe.systemsConnected(sysID, homeSystemID, empireID) ] currentMilSystems = [sid for sid, alloc, takeAny, multiplier in allocations if alloc > 0 ] borderTargets1 = [sid for sid in accessibleSystemIDs if ( ( sid not in currentMilSystems )) ] borderTargets = [sid for sid in borderTargets1 if ( ( threatBias +foAI.foAIstate.systemStatus.get(sid, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(sid, {}).get('planetThreat', 0) > 0.8*alreadyAssignedRating[sid] )) ] if "Main" in round: print "" print "Empire-Accessible Systems not yet allocated military: %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID) and universe.getSystem(sysID).name) for sysID in borderTargets1 ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety newAlloc=0 if len(borderTargets) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, threatBias +safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0)+ foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0)) ) for oSID in borderTargets ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=alreadyAssignedRating[sid] neededRating = ratingNeeded( 1.2*thrt, curAlloc) thisAlloc=0 #only record more allocation for this invasion if we already started or have enough rating available takeAny= False if ( neededRating>0 ) and (remainingMilRating > neededRating or takeAny): thisAlloc = max(0, min( neededRating, remainingMilRating)) newAlloc+=thisAlloc maxAlloc = safetyFactor*2*max( foAI.foAIstate.systemStatus.get(sid, {}).get('totalThreat', 0), foAI.foAIstate.systemStatus.get(sid, {}).get('neightborThreat', 0)) allocations.append( (sid, thisAlloc, takeAny , maxAlloc) ) allocationGroups.setdefault('accessibleTargets', []).append( (sid, thisAlloc, takeAny , maxAlloc) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Other Empire-Accessible system %4d ( %10s ) has local biased threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" print "Other Empire-Accessible Systems under total biased threat: %d -- total mil allocation-- existing: %d ; new: %d"%(tototSysThreat, totCurAlloc, otSysAlloc ) print "-----------------" elif "Main" in round: print "-----------------" print "No Other Empire-Accessible Systems with biased local threat " print "-----------------" #monster den treatment probably unnecessary now if "Main" in round: print "" print "Big-Monster Dens: %s"%( [ "| %d %s |"%(sysID, universe.getSystem(sysID).name) for sysID in monsterDens ] ) print "-----------------" # for these, calc fleet threat only, no neighbor threat, but use a multiplier for fleet safety newAlloc=0 if len(monsterDens) > 0: otSysAlloc = 0 otSysThreat = [ ( oSID, safetyFactor*(foAI.foAIstate.systemStatus.get(oSID, {}).get('fleetThreat', 0)+foAI.foAIstate.systemStatus.get(oSID, {}).get('monsterThreat', 0) + foAI.foAIstate.systemStatus.get(oSID, {}).get('planetThreat', 0) ) ) for oSID in monsterDens ] tototSysThreat = sum( [thrt for sid, thrt in otSysThreat] ) totCurAlloc = sum( [0.8*alreadyAssignedRating[sid] for sid, thrt in otSysThreat] ) for sid, thrt in otSysThreat: curAlloc=0.8*alreadyAssignedRating[sid] thisAlloc=0 if (thrt > curAlloc) and remainingMilRating > 2* thrt: thisAlloc = int(0.99999 + (thrt-curAlloc)*1.5) newAlloc+=thisAlloc allocations.append( (sid, thisAlloc, False, 5) ) remainingMilRating -= thisAlloc otSysAlloc += thisAlloc if "Main" in round or thisAlloc >0: print "Monster Den %4d ( %10s ) has local threat %8d ; existing military allocation %d and new allocation %8d"%(sid, universe.getSystem(sid).name, thrt, curAlloc, thisAlloc) if "Main" in round or newAlloc >0: print "-----------------" if remainingMilRating <=6: newAllocations = [ (sid, alc, alc, ta) for (sid, alc, ta, mm) in allocations ] else: #oldAllocations = dict( [ (entry[0], entry ) for entry in allocations ] ) try: totAlloc = sum( [alloc for sid, alloc, takeAny, maxAlloc in allocations ] ) except: print "error unpacking sid, alloc, takeAny, maxAlloc from ", allocations factor =(2.0* remainingMilRating ) / ( totAlloc + 0.1) #print "Remaining military strength allocation %d will be allocated as %.1f %% surplus allocation to top current priorities"%(remainingMilRating, 100*factor) print "%s Round Remaining military strength allocation %d will be allocated as surplus allocation to top current priorities"%(round, remainingMilRating) newAllocations = [] for cat in ['capitol', 'topTargets', 'otherTargets', 'accessibleTargets', 'occupied', 'exploreTargets']: for sid, alloc, takeAny, maxAlloc in allocationGroups.get(cat, []): if remainingMilRating <= 0 : newAllocations.append( ( sid, alloc, alloc, takeAny ) ) else: newRating = min(remainingMilRating+alloc, max(alloc, ratingNeeded( maxAlloc, alreadyAssignedRating[sid]) ) ) newAllocations.append( ( sid, newRating, alloc, takeAny ) ) remainingMilRating -= ( newRating - alloc ) if "Main" in round: MilitaryAllocations = newAllocations minMilAllocations = dict( [ (sid, alloc) for sid, alloc, takeAny, mm in allocations ] ) print "------------------------------\nFinal %s Round Military Allocations: %s \n-----------------------"%(round, dict( [ (sid, alloc) for sid, alloc, minalloc, takeAny in newAllocations ] ) ) # export military systems for other AI modules if "Main" in round: AIstate.militarySystemIDs = list( set([sid for sid, alloc, minalloc, takeAny in newAllocations]).union( [sid for sid in alreadyAssignedRating if alreadyAssignedRating[sid]>0 ] )) else: AIstate.militarySystemIDs = list( set([sid for sid, alloc, minalloc, takeAny in newAllocations]).union( AIstate.militarySystemIDs) ) return newAllocations
def getInvasionFleets(): "get invasion fleets" allInvasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION) AIstate.invasionFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allInvasionFleetIDs) # get supplyable 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: homeSystemID = homeworld.systemID else: speciesName = "" homeworldName=" no remaining homeworld " homeSystemID = -1 fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs) primeInvadableSystemIDs1 = set([]) primeInvadableSystemIDs = set([]) print "Current Fleet Supplyable Systems: ", sysNameIDs(empire.fleetSupplyableSystemIDs) for sysID in empire.fleetSupplyableSystemIDs: primeInvadableSystemIDs.add(sysID) for nID in universe.getImmediateNeighbors(sysID, empireID): primeInvadableSystemIDs.add(nID) primeInvadableSystemIDs1.add(nID) primeInvadableSystemIDs1.difference_update(empire.fleetSupplyableSystemIDs) print "First Ring of invadable systems: ", sysNameIDs(primeInvadableSystemIDs1) if empire.getTechStatus("CON_ORBITAL_CON") == fo.techStatus.complete: primeInvadableSystemIDs2 = set([]) for sysID in list(primeInvadableSystemIDs1): for nID in universe.getImmediateNeighbors(sysID, empireID): primeInvadableSystemIDs2.add(nID) primeInvadableSystemIDs2.difference_update(primeInvadableSystemIDs) print "Second Ring of invadable systems: ", sysNameIDs(primeInvadableSystemIDs2) primeInvadableSystemIDs.update(primeInvadableSystemIDs2) primeInvadableSystemIDs3 = set([]) if foAI.foAIstate.aggression > 1: for sysID in list(primeInvadableSystemIDs2): for nID in universe.getImmediateNeighbors(sysID, empireID): primeInvadableSystemIDs3.add(nID) primeInvadableSystemIDs3.difference_update(primeInvadableSystemIDs) print "Third Ring of invadable systems: ", sysNameIDs(primeInvadableSystemIDs3) primeInvadableSystemIDs.update(primeInvadableSystemIDs3) primeInvadablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(primeInvadableSystemIDs) # get competitor planets exploredSystemIDs = empire.exploredSystemIDs exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs) visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() visiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(visibleSystemIDs) accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if universe.systemsConnected(sysID, homeSystemID, empireID) ] acessiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(accessibleSystemIDs) #allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(exploredPlanetIDs) allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(acessiblePlanetIDs) # print "All Owned and Populated PlanetIDs: " + str(allOwnedPlanetIDs) allPopulatedPlanets=PlanetUtilsAI.getPopulatedPlanetIDs(acessiblePlanetIDs) print "All Visible and accessible Populated PlanetIDs (including this empire's): " + str(planetNameIDs(allPopulatedPlanets)) empireOwnedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) # print "Empire Owned PlanetIDs: " + str(empireOwnedPlanetIDs) invadablePlanetIDs = set(primeInvadablePlanetIDs).intersection(set(allPopulatedPlanets) - set(empireOwnedPlanetIDs)) print "Prime Invadable PlanetIDs: " + str(planetNameIDs(invadablePlanetIDs)) print "" print "Invasion Targeted SystemIDs: " + str(sysNameIDs(AIstate.invasionTargetedSystemIDs)) invasionTargetedPlanetIDs = getInvasionTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_INVASION, empireID) allInvasionTargetedSystemIDs = PlanetUtilsAI.getSystems(invasionTargetedPlanetIDs) # export invasion targeted systems for other AI modules AIstate.invasionTargetedSystemIDs = allInvasionTargetedSystemIDs print "Invasion Targeted PlanetIDs: " + str(planetNameIDs(invasionTargetedPlanetIDs)) invasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION) if not invasionFleetIDs: print "Available Invasion Fleets: 0" else: print "Invasion FleetIDs: " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION)) numInvasionFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(invasionFleetIDs)) print "Invasion Fleets Without Missions: " + str(numInvasionFleets) evaluatedPlanetIDs = list(set(invadablePlanetIDs) - set(invasionTargetedPlanetIDs)) print "Evaluating potential invasions, PlanetIDs: " + str(evaluatedPlanetIDs) evaluatedPlanets = assignInvasionValues(evaluatedPlanetIDs, AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire) sortedPlanets = [(pid, pscore, ptroops) for (pid, (pscore, ptroops)) in evaluatedPlanets.items() ] sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True) print "" if sortedPlanets: print "Invadable planetIDs, ID | Score | Race | Troops | Name:" for pid, pscore, ptroops in sortedPlanets: planet = universe.getPlanet(pid) if planet: print "%6d | %6d | %s | %s | %d"%(pid, pscore, planet.name, planet.speciesName, ptroops) else: print "%6d | %6d | Error: invalid planet ID"%(pid, pscore) else: print "No Invadable planets identified" # export opponent planets for other AI modules AIstate.opponentPlanetIDs = [pid for pid, pscore, trp in sortedPlanets] AIstate.invasionTargets = sortedPlanets
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 getInvasionFleets(): "get invasion fleets" times=[] tasks = [] times.append( time() ) tasks.append("init") allInvasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION) AIstate.invasionFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allInvasionFleetIDs) # get supplyable 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: homeSystemID = homeworld.systemID else: speciesName = "" homeworldName=" no remaining homeworld " homeSystemID = -1 fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs) primeInvadableSystemIDs = set(ColonisationAI.annexableSystemIDs) primeInvadablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(primeInvadableSystemIDs) # get competitor planets exploredSystemIDs = empire.exploredSystemIDs exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs) visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() visiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(visibleSystemIDs) if homeSystemID != -1: accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if (sysID != -1 ) and universe.systemsConnected(sysID, homeSystemID, empireID) ] else: print "Invasion Warning: this empire has no identifiable homeworld, will therefor treat all visible planets as accessible." accessibleSystemIDs = visibleSystemIDs #TODO: check if any troop ships still owned, use their system as home system acessiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(accessibleSystemIDs) print "Accessible Systems: " + str(PlanetUtilsAI.sysNameIDs(accessibleSystemIDs)) print #allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(exploredPlanetIDs) allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(acessiblePlanetIDs)#need these for unpopulated outposts # print "All Owned and Populated PlanetIDs: " + str(allOwnedPlanetIDs) allPopulatedPlanets=PlanetUtilsAI.getPopulatedPlanetIDs(acessiblePlanetIDs)#need this for natives print "All Visible and accessible Populated PlanetIDs (including this empire's): " + str(PlanetUtilsAI.planetNameIDs(allPopulatedPlanets)) print print "Prime Invadable Target Systems: " + str(PlanetUtilsAI.sysNameIDs(primeInvadableSystemIDs)) print empireOwnedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) # print "Empire Owned PlanetIDs: " + str(empireOwnedPlanetIDs) invadablePlanetIDs = set(primeInvadablePlanetIDs).intersection(set(allOwnedPlanetIDs).union(allPopulatedPlanets) - set(empireOwnedPlanetIDs)) print "Prime Invadable PlanetIDs: " + str(PlanetUtilsAI.planetNameIDs(invadablePlanetIDs)) print "" print "Current Invasion Targeted SystemIDs: " + str(PlanetUtilsAI.sysNameIDs(AIstate.invasionTargetedSystemIDs)) invasionTargetedPlanetIDs = getInvasionTargetedPlanetIDs(universe.planetIDs, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, empireID) invasionTargetedPlanetIDs.extend( getInvasionTargetedPlanetIDs(universe.planetIDs, EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION, empireID)) allInvasionTargetedSystemIDs = set(PlanetUtilsAI.getSystems(invasionTargetedPlanetIDs)) print "Current Invasion Targeted PlanetIDs: " + str(PlanetUtilsAI.planetNameIDs(invasionTargetedPlanetIDs)) invasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION) if not invasionFleetIDs: print "Available Invasion Fleets: 0" else: print "Invasion FleetIDs: " + str(FleetUtilsAI.getEmpireFleetIDsByRole(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)) numInvasionFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(invasionFleetIDs)) print "Invasion Fleets Without Missions: " + str(numInvasionFleets) times.append( time() ) tasks.append( "gathering initial info" ) availablePP = {} for el in empire.planetsWithAvailablePP: #keys are sets of ints; data is doubles avail_pp = el.data() for pid in el.key(): availablePP[pid] = avail_pp if len (invadablePlanetIDs) > 0: #print "Evaluating Troop Bases (SpaceInvaders) for %s"%(invadablePlanetIDs) pass for pid in invadablePlanetIDs: #TODO: reorganize planet = universe.getPlanet(pid) if not planet: continue sysID = planet.systemID sysPartialVisTurn = dictFromMap(universe.getVisibilityTurnsMap(planet.systemID, empireID)).get(fo.visibility.partial, -9999) planetPartialVisTurn = dictFromMap(universe.getVisibilityTurnsMap(pid, empireID)).get(fo.visibility.partial, -9999) if (planetPartialVisTurn < sysPartialVisTurn): #print "rejecting %s due to stealth"%planet.name continue for pid2 in ColonisationAI.empireSpeciesSystems.get(sysID, {}).get('pids', []): if availablePP.get(pid2, 0) < 2: #TODO: improve troop base PP sufficiency determination #print "rejecting %s due to insufficient avail PP"%planet.name break planet2 = universe.getPlanet(pid2) if not planet2: continue if (pid not in foAI.foAIstate.qualifyingTroopBaseTargets) and (planet2.speciesName in ColonisationAI.empireShipBuilders): #print "Adding %s to Troop Bases (SpaceInvaders) potential target list, from %s"%(planet.name, planet2.name) foAI.foAIstate.qualifyingTroopBaseTargets.setdefault(pid, [pid2, -1]) break for pid in list(foAI.foAIstate.qualifyingTroopBaseTargets): planet = universe.getPlanet(pid) if planet and planet.owner == empireID: del foAI.foAIstate.qualifyingTroopBaseTargets[pid] reserved_troop_base_targets = [] secureAIFleetMissions = foAI.foAIstate.getAIFleetMissionsWithAnyMissionTypes([EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE]) #print "considering possible troop bases at %s" % (foAI.foAIstate.qualifyingTroopBaseTargets.keys()) for pid in (set(foAI.foAIstate.qualifyingTroopBaseTargets.keys()) - set(invasionTargetedPlanetIDs)): #TODO: consider overriding standard invasion mission planet = universe.getPlanet(pid) if foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] != -1: reserved_troop_base_targets.append(pid) if planet: allInvasionTargetedSystemIDs.add( planet.systemID ) continue #already building for here loc = foAI.foAIstate.qualifyingTroopBaseTargets[pid][0] this_score, p_troops = evaluateInvasionPlanet(pid, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire, secureAIFleetMissions, False) if (planet.currentMeterValue(fo.meterType.shield)) > 0: continue bestShip, colDesign, buildChoices = ProductionAI.getBestShipInfo(EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_ORBITAL_INVASION, loc) if not bestShip: #print "Error: no troop base can be built at ", PlanetUtilsAI.planetNameIDs([loc]) continue #print "selecting ", PlanetUtilsAI.planetNameIDs([loc]), " to build Orbital troop bases" n_bases = math.ceil((p_troops+1) / 2)#TODO: reconsider this +1 safety factor retval = fo.issueEnqueueShipProductionOrder(bestShip, loc) print "Enqueueing %d Troop Bases at %s for %s"%( n_bases, PlanetUtilsAI.planetNameIDs([loc]), PlanetUtilsAI.planetNameIDs([pid])) if retval !=0: allInvasionTargetedSystemIDs.add( planet.systemID ) reserved_troop_base_targets.append(pid) foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] = loc fo.issueChangeProductionQuantityOrder(empire.productionQueue.size -1, 1, int(n_bases)) res=fo.issueRequeueProductionOrder(empire.productionQueue.size -1, 0) times.append( time() ) tasks.append( "planning troop base production" ) #TODO: check if any invasionTargetedPlanetIDs need more troops assigned evaluatedPlanetIDs = list(set(invadablePlanetIDs) - set(invasionTargetedPlanetIDs) - set(reserved_troop_base_targets) ) print "Evaluating potential invasions, PlanetIDs: " + str(evaluatedPlanetIDs) evaluatedPlanets = assignInvasionValues(evaluatedPlanetIDs, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire) sortedPlanets = [(pid, pscore, ptroops) for (pid, (pscore, ptroops)) in evaluatedPlanets.items() ] sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True) sortedPlanets = [(pid, pscore%10000, ptroops) for (pid, pscore, ptroops) in sortedPlanets ] times.append( time() ) tasks.append( "evaluating %d target planets"%(len(evaluatedPlanetIDs)) ) print "" if sortedPlanets: print "Invadable planets\nIDs, ID | Score | Name | Race | Troops" for pid, pscore, ptroops in sortedPlanets: planet = universe.getPlanet(pid) if planet: print "%6d | %6d | %16s | %16s | %d"%(pid, pscore, planet.name, planet.speciesName, ptroops) else: print "%6d | %6d | Error: invalid planet ID"%(pid, pscore) else: print "No Invadable planets identified" sortedPlanets = [(pid, pscore, ptroops) for (pid, pscore, ptroops) in sortedPlanets if pscore > 0] # export opponent planets for other AI modules AIstate.opponentPlanetIDs = [pid for pid, pscore, trp in sortedPlanets] AIstate.invasionTargets = sortedPlanets # export invasion targeted systems for other AI modules AIstate.invasionTargetedSystemIDs = list(allInvasionTargetedSystemIDs) times.append( time() ) tasks.append( "total processing" ) for t_index in range(1, len(times)-1): print "getInvasionFleets(): %40s took %d msec"%(tasks[t_index], int(1000*(times[t_index]-times[t_index-1]))) print "getInvasionFleets(): %40s took %d msec"%(tasks[-1], int(1000*(times[-1]-times[0])))
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire): "return the invasion value of a planet" 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 bldTally=0 for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]: bldTally += buildingValues.get(bldType, 50) 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) specName=planet.speciesName species=fo.getSpecies(specName) popTSize = planet.currentMeterValue(fo.meterType.targetPopulation)#TODO: adjust for empire tech planetSpecials = list(planet.specials) pSysID = planet.systemID#TODO: check star value indVal = 0 basePopInd=0.2 prodFactor = 1 discountMultiplier=20 for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : if special in planetSpecials: prodFactor+=1 proSingVal = [0, 4][(len( AIstate.empireStars.get(fo.starType.blackHole, [])) > 0)] indTechMap={ "GRO_ENERGY_META": 0.5, "PRO_ROBOTIC_PROD":0.4, "PRO_FUSION_GEN": 1.0, "PRO_INDUSTRY_CENTER_I": 1, "PRO_INDUSTRY_CENTER_II":1, "PRO_INDUSTRY_CENTER_III":1, "PRO_SOL_ORB_GEN": 2.0, #assumes will build a gen at a blue/white star "PRO_SINGULAR_GEN": proSingVal, } for tech in indTechMap: if (empire.getTechStatus(tech) == fo.techStatus.complete): prodFactor += indTechMap[tech] indVal = discountMultiplier * basePopInd *prodFactor*popTSize if (empire.getTechStatus("PRO_SENTIENT_AUTOMATION") == fo.techStatus.complete): indVal += discountMultiplier * 5 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* max(planet.currentMeterValue(fo.meterType.targetIndustry), 2*planet.currentMeterValue(fo.meterType.targetResearch)) if not species:#TODO: perhaps stealth makes planet inacccesible & should abort try: targetPop=planet.currentMeterValue(fo.meterType.targetPopulation) popVal = 2*targetPop except: popVal=0 else: popVal = evaluatePlanet(planetID, AIFleetMissionType.FLEET_MISSION_COLONISATION, [planetID], species, empire) #evaluatePlanet is imported from ColonisationAI if planetID in fleetSupplyablePlanetIDs: #TODO: extend to rings supplyVal = 100 if planet.owner== -1: #if (pmaxShield <10): if ( sysFThrt < 0.5*curBestMilShipRating() ): if ( sysMThrt < 3*curBestMilShipRating()): supplyVal = 10000 else: supplyVal = 50 planetSpecials = list(planet.specials) specialVal=0 if ( ( planet.size == fo.planetSize.asteroids ) and (empire.getTechStatus("PRO_ASTEROID_MINE") == fo.techStatus.complete ) ): specialVal= 15 #TODO: should do more eval re asteroid mining here for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : if special in planetSpecials: specialVal +=10 # buildTime=4 return max(0, popVal+supplyVal+specialVal+bldTally+indVal+enemyVal-20*troops), min(troops+maxJumps+buildTime, maxTroops)
def getInvasionFleets(): "get invasion fleets" allInvasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION) AIstate.invasionFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allInvasionFleetIDs) # get supplyable 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: homeSystemID = homeworld.systemID else: speciesName = "" homeworldName=" no remaining homeworld " homeSystemID = -1 fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs) primeInvadableSystemIDs = set(ColonisationAI.annexableSystemIDs) primeInvadablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(primeInvadableSystemIDs) # get competitor planets exploredSystemIDs = empire.exploredSystemIDs exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs) visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys() visiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(visibleSystemIDs) accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if universe.systemsConnected(sysID, homeSystemID, empireID) ] acessiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(accessibleSystemIDs) #allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(exploredPlanetIDs) allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(acessiblePlanetIDs) # print "All Owned and Populated PlanetIDs: " + str(allOwnedPlanetIDs) allPopulatedPlanets=PlanetUtilsAI.getPopulatedPlanetIDs(acessiblePlanetIDs) print "All Visible and accessible Populated PlanetIDs (including this empire's): " + str(PlanetUtilsAI.planetNameIDs(allPopulatedPlanets)) empireOwnedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) # print "Empire Owned PlanetIDs: " + str(empireOwnedPlanetIDs) invadablePlanetIDs = set(primeInvadablePlanetIDs).intersection(set(allPopulatedPlanets) - set(empireOwnedPlanetIDs)) print "Prime Invadable PlanetIDs: " + str(PlanetUtilsAI.planetNameIDs(invadablePlanetIDs)) print "" print "Current Invasion Targeted SystemIDs: " + str(PlanetUtilsAI.sysNameIDs(AIstate.invasionTargetedSystemIDs)) invasionTargetedPlanetIDs = getInvasionTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_INVASION, empireID) allInvasionTargetedSystemIDs = PlanetUtilsAI.getSystems(invasionTargetedPlanetIDs) # export invasion targeted systems for other AI modules AIstate.invasionTargetedSystemIDs = allInvasionTargetedSystemIDs print "Current Invasion Targeted PlanetIDs: " + str(PlanetUtilsAI.planetNameIDs(invasionTargetedPlanetIDs)) invasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION) if not invasionFleetIDs: print "Available Invasion Fleets: 0" else: print "Invasion FleetIDs: " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION)) numInvasionFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(invasionFleetIDs)) print "Invasion Fleets Without Missions: " + str(numInvasionFleets) evaluatedPlanetIDs = list(set(invadablePlanetIDs) - set(invasionTargetedPlanetIDs)) print "Evaluating potential invasions, PlanetIDs: " + str(evaluatedPlanetIDs) evaluatedPlanets = assignInvasionValues(evaluatedPlanetIDs, AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire) sortedPlanets = [(pid, pscore, ptroops) for (pid, (pscore, ptroops)) in evaluatedPlanets.items() ] sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True) sortedPlanets = [(pid, pscore%10000, ptroops) for (pid, pscore, ptroops) in sortedPlanets ] print "" if sortedPlanets: print "Invadable planets\nIDs, ID | Score | Name | Race | Troops" for pid, pscore, ptroops in sortedPlanets: planet = universe.getPlanet(pid) if planet: print "%6d | %6d | %16s | %16s | %d"%(pid, pscore, planet.name, planet.speciesName, ptroops) else: print "%6d | %6d | Error: invalid planet ID"%(pid, pscore) else: print "No Invadable planets identified" # export opponent planets for other AI modules AIstate.opponentPlanetIDs = [pid for pid, pscore, trp in sortedPlanets] AIstate.invasionTargets = sortedPlanets
def generateOrders(): global lastTurnTimestamp universe = fo.getUniverse() turnStartTime=time() #starting AI timer here, to be sure AI doesn't get blame for any lags in server being able to provide the Universe object empire = fo.getEmpire() planetID = PlanetUtilsAI.getCapital() planet=None if planetID is not None: planet = universe.getPlanet(planetID) print "***************************************************************************" print "***************************************************************************" print ("Generating Orders") print "EmpireID: " + str(empire.empireID) + " Name: " + empire.name+ "_"+str(empire.empireID-1) +"_pid:"+str(fo.playerID())+"_"+fo.playerName()+"_"+aggressions.get(foAIstate.aggression, "?") + " Turn: " + str(fo.currentTurn()) empireColor=empire.colour print "EmpireColors: %d %d %d %d"%(empireColor.r, empireColor.g, empireColor.b, empireColor.a) if planet: print "CapitalID: " + str(planetID) + " Name: " + planet.name + " Species: " + planet.speciesName else: print "CapitalID: None Currently Name: None Species: None " print "***************************************************************************" print "***************************************************************************" if fo.currentTurn() == 1: declareWarOnAll() # turn cleanup !!! this was formerly done at start of every turn -- not sure why splitNewFleets() #updateShipDesigns() #should not be needed anymore; #updateFleetsRoles() foAIstate.clean() #checks exploration border & clears roles/missions of missing fleets & updates fleet locs foAIstate.reportSystemThreats() # ...missions # ...demands/priorities print("Calling AI Modules") # call AI modules timer=[time()] try: PriorityAI.calculatePriorities() except: print "Error: exception triggered and caught: ", traceback.format_exc() # try traceback.print_exc() timer.append( time() ) try: ExplorationAI.assignScoutsToExploreSystems() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: ColonisationAI.assignColonyFleetsToColonise() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: InvasionAI.assignInvasionFleetsToInvade() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: MilitaryAI.assignMilitaryFleetsToSystems() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: FleetUtilsAI.generateAIFleetOrdersForAIFleetMissions() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: FleetUtilsAI.issueAIFleetOrdersForAIFleetMissions() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: ResearchAI.generateResearchOrders() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: ProductionAI.generateProductionOrders() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: ResourcesAI.generateResourcesOrders() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) try: foAIstate.afterTurnCleanup() except: print "Error: exception triggered and caught: ", traceback.format_exc() timer.append( time() ) times = [timer[i] - timer[i-1] for i in range(1, len(timer) ) ] turnEndTime=time() timeFmt = "%30s: %8d msec " print "AI Module Time Requirements:" for mod, modTime in zip(__timerEntries, times): print timeFmt%((30*' '+mod)[-30:], int(1000*modTime)) if __timerFile: __timerFile.write( __timerFileFmt%tuple( [ fo.currentTurn() ]+map(lambda x: int(1000*x), times )) +'\n') __timerFile.flush() if __timerBucketFile: __timerBucketFile.write( __timerBucketFileFmt%tuple( [ fo.currentTurn(), (turnStartTime-lastTurnTimestamp)*1000, (turnEndTime-turnStartTime)*1000 ]) +'\n') __timerBucketFile.flush() lastTurnTimestamp = time() try: fo.doneTurn() except: print "Error: exception triggered and caught: ", traceback.format_exc()
def evaluatePlanet(planetID, missionType, fleetSupplyablePlanetIDs, species, empire): "returns the colonisation value of a planet" # TODO: in planet evaluation consider specials and distance discountMultiplier = 20.0 priorityScaling=1.0 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 colonyStarBonus=0 if species: tagList = [tag for tag in species.tags] starPopMod=0 if system: if "PHOTOTROPHIC" in tagList: starPopMod = photoMap.get( system.starType, 0 ) 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 +=20* discountMultiplier elif planet.systemID not in (AIstate.popCtrSystemIDs + AIstate.outpostSystemIDs) : starBonus +=1+10*discountMultiplier #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 system.starType in [fo.starType.blackHole] : starBonus +=50*discountMultiplier #whether have tech yet or not, assign some base value 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 +=200*discountMultiplier #pretty rare planets, good for generator elif planet.systemID not in (AIstate.popCtrSystemIDs + AIstate.outpostSystemIDs): starBonus +=100*discountMultiplier #still has extra value as an alternate location for generators & for bnlocking enemies generators elif system.starType in [fo.starType.red] and ( len (AIstate.empireStars.get(fo.starType.blackHole, [])) + len (AIstate.empireStars.get(fo.starType.red, [])))==0: if planet.systemID not in (AIstate.popCtrSystemIDs + AIstate.outpostSystemIDs): starBonus +=40*discountMultiplier # can be used for artificial black hole 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 +=80*discountMultiplier #pretty rare planets, good for armor else: starBonus +=20*discountMultiplier #still has extra value as an alternate location for generators & for bnlocking enemies generators if (empire.getTechStatus("SHP_ENRG_BOUND_MAN") == fo.techStatus.complete) or ( "SHP_ENRG_BOUND_MAN" in empireResearchList[:6]) : if system.starType in [fo.starType.blackHole, fo.starType.blue] : if len (AIstate.empireStars.get(fo.starType.blackHole, []) + AIstate.empireStars.get(fo.starType.blue, []) ) ==0: colonyStarBonus +=100*discountMultiplier #pretty rare planets, good for generator elif planet.systemID not in (AIstate.popCtrSystemIDs + AIstate.outpostSystemIDs): colonyStarBonus +=50*discountMultiplier #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+=5*discountMultiplier # get an outpost on the nest quick if ( ( planet.size == fo.planetSize.asteroids ) and (empire.getTechStatus("PRO_MICROGRAV_MAN") == fo.techStatus.complete )): if system: astVal=0 for pid in system.planetIDs: otherPlanet=universe.getPlanet(pid) if otherPlanet.size == fo.planetSize.asteroids: if pid==planetID: continue elif pid < planetID: astVal=0 break elif otherPlanet.size!= fo.planetSize.gasGiant and otherPlanet.owner==empire.empireID: astVal+=20 * discountMultiplier retval += astVal if ( ( planet.size == fo.planetSize.gasGiant ) and ( (empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete ) or ( "PRO_ORBITAL_GEN" in empireResearchList[:3]) )): if system: orbGenVal=0 for pid in system.planetIDs: otherPlanet=universe.getPlanet(pid) if otherPlanet.size == fo.planetSize.asteroids and otherPlanet.owner==empire.empireID: if empire.getTechStatus("PRO_EXOBOTS") == fo.techStatus.complete: orbGenVal+=10*discountMultiplier elif otherPlanet.size!= fo.planetSize.gasGiant and otherPlanet.owner==empire.empireID: orbGenVal+=10*discountMultiplier retval += orbGenVal if ( foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0) + foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('monsterThreat', 0) )> 2*curBestMilShipRating: retval = retval / 2.0 return int(retval) else: #colonization mission retval += colonyStarBonus asteroidBonus=0 gasGiantBonus=0 miningBonus=0 maxGGGs=8 perGGG=9*discountMultiplier planetSize = planet.size 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 : if ( (empire.getTechStatus("PRO_MICROGRAV_MAN") == fo.techStatus.complete ) or ( "PRO_MICROGRAV_MAN" in empireResearchList[:3]) ): asteroidBonus = 5*discountMultiplier if p2.size== fo.planetSize.gasGiant : if ( (empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete ) or ( "PRO_ORBITAL_GEN" in empireResearchList[:3]) ): gasGiantBonus += perGGG gasGiantBonus = min( gasGiantBonus, maxGGGs * perGGG ) if (planet.size==fo.planetSize.gasGiant): if not (species and species.name == "SP_SUPER_TEST"): return 0 else: planetEnv = fo.planetEnvironment.good#I think planetSize=4 #I think elif ( planet.size == fo.planetSize.asteroids ): planetSize=3 #I think if not species or (species.name not in [ "SP_EXOBOT", "SP_SUPER_TEST" ]): return 0 elif species.name == "SP_EXOBOT": planetEnv =fo.planetEnvironment.poor elif species.name == "SP_SUPER_TEST": planetEnv = fo.planetEnvironment.good#I think else: return 0 else: planetEnv = environs[ str(species.getPlanetEnvironment(planet.type)) ] if planetEnv==0: return -9999 popSizeMod=0 popSizeMod += popSizeModMap["env"][planetEnv] if "SELF_SUSTAINING" in tagList: popSizeMod*=2 popSizeMod += starPopMod if (empire.getTechStatus("GRO_SUBTER_HAB") == fo.techStatus.complete) or "TUNNELS_SPECIAL" in planetSpecials: 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] if empire.getTechStatus("CON_NDIM_STRUC") == fo.techStatus.complete: popSizeMod += popSizeModMap["ndim"][planetEnv] if empire.getTechStatus("CON_ORBITAL_HAB") == fo.techStatus.complete: popSizeMod += popSizeModMap["orbit"][planetEnv] if "GAIA_SPECIAL" in planet.specials: popSizeMod += 3 for special in [ "SLOW_ROTATION_SPECIAL", "SOLID_CORE_SPECIAL"] : if special in planetSpecials: popSizeMod -= 1 """ 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"), ]: """ for special in [ spec for spec in AIDependencies.metabolimBoosts if spec in planetSpecials]: valMod += 3*discountMultiplier # extra bonus due to potential applicability to other planets for thisTag in [ tag for tag in tagList if tag in AIDependencies.metabolims]: popSizeMod += len( (set(planetSpecials).union([key for key in activeGrowthSpecials.keys() if len(activeGrowthSpecials[key])>0 ] )).intersection(AIDependencies.metabolimBoostMap.get(thisTag, []) ) ) popSize = planetSize * popSizeMod if "DIM_RIFT_MASTER_SPECIAL" in planet.specials: popSize -= 4 for special in [ "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "METALOIDS_SPECIAL"] : if special in planetSpecials: miningBonus+=1 proSingVal = [0, 4][(len( AIstate.empireStars.get(fo.starType.blackHole, [])) > 0)] basePopInd=0.2 indTechMap={ "GRO_ENERGY_META": 0.5, "PRO_ROBOTIC_PROD":0.4, "PRO_FUSION_GEN": 1.0, "PRO_INDUSTRY_CENTER_I": 1, "PRO_INDUSTRY_CENTER_II":1, "PRO_INDUSTRY_CENTER_III":1, "PRO_SOL_ORB_GEN": 2.0, #assumes will build a gen at a blue/white star "PRO_SINGULAR_GEN": proSingVal, } indVal = 0 if (empire.getTechStatus("PRO_SENTIENT_AUTOMATION") == fo.techStatus.complete): indVal += discountMultiplier * 5 indVal += discountMultiplier * basePopInd * popSize*miningBonus for tech in indTechMap: if (empire.getTechStatus(tech) == fo.techStatus.complete): indVal += discountMultiplier * basePopInd * popSize * indTechMap[tech] # used to 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 retval=0.0 if popSize<0: if foAI.foAIstate.aggression > fo.aggression.typical and (fo.currentTurn() >= 10): retval = starBonus+asteroidBonus+gasGiantBonus elif popSize==0: if foAI.foAIstate.aggression > fo.aggression.typical and (fo.currentTurn() >= 10): retval = 0.6*( starBonus+asteroidBonus+gasGiantBonus) #actually is kind of a pain if the pop goes close to zero but not actually zero else: retval = starBonus+indVal+asteroidBonus+gasGiantBonus + valMod if planet.systemID in annexableRing1: retval += 10 elif planet.systemID in annexableRing2: retval += 20 elif planet.systemID in annexableRing3: retval += 10 if (gasGiantBonus ==0): if ( indVal + valMod < 10*discountMultiplier): if fo.currentTurn() < 15: priorityScaling = 0 elif fo.currentTurn() < 50: priorityScaling = 0.5 retval *= priorityScaling thrtRatio = (foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('fleetThreat', 0)+foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('monsterThreat', 0)+0.2*foAI.foAIstate.systemStatus.get(planet.systemID, {}).get('neighborThreat', 0)) / float(curBestMilShipRating) if thrtRatio > 4: retval = 0.3*retval elif thrtRatio >= 2: retval = 0.7* retval elif thrtRatio > 0: retval = 0.85* retval return retval
def setGeneralPlanetResourceFocus(): "set resource focus of planets except capitalID, asteroids, and gas giants" global __timerFile universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID timer= [ time() ] # getPlanets empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) timer.append( time() ) #filter capitalIDL = [PlanetUtilsAI.getCapital()] asteroids = PlanetUtilsAI.getTypePlanetEmpireOwned(fo.planetType.asteroids) gasGiants = PlanetUtilsAI.getTypePlanetEmpireOwned(fo.planetType.gasGiant) generalPlanetIDs = list(set(empirePlanetIDs) - (set(capitalIDL)|set(asteroids)|set(gasGiants))) timer.append( time() ) #Priority #fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs #fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs) ppPrio = foAI.foAIstate.getPriority(AIPriorityType.PRIORITY_RESOURCE_PRODUCTION) rpPrio = foAI.foAIstate.getPriority(AIPriorityType.PRIORITY_RESOURCE_RESEARCH) priorityRatio = float(ppPrio)/(rpPrio+0.0001) timer.append( time() ) # shuffle # not supporting Growth for general planets until also adding code to make sure would actually benefit shuffle(generalPlanetIDs) timer.append( time() ) # targets pp, rp = getResourceTargetTotals() targetRatio = pp/(rp+0.0001) nplanets = len(generalPlanetIDs) nChanges = int( ( nplanets * max( 1.0/(rp+0.001), 2.0/(pp+0.0001)) * ( (pp - rp* priorityRatio)/(priorityRatio +2))) +0.5 ) # weird formula I came up with to estimate desired number of changes print "current target totals -- pp: %.1f rp: %.1f ; ratio %.2f ; desired ratio %.2f will change up to %d foci from total of %d planets"%(pp, rp, targetRatio, priorityRatio, nChanges, nplanets) timer.append( time() ) #loop iChanges = 0 for planetID in generalPlanetIDs: if iChanges >= nChanges: break planet = universe.getPlanet(planetID) oldFocus=planet.focus targetRatio = pp/(rp + 0.0001) ratioRatio = priorityRatio / ( targetRatio + 0.0001) if (AIFocusType.FOCUS_MINING in planet.availableFoci): #and ((priorityRatio > 0.5 ) or ( ratioRatio > 0.9 ) ) : #could be a more complex decision here, if oldFocus != AIFocusType.FOCUS_MINING: iChanges +=1 #even if not necessarily directed towards desired ratio fo.issueChangeFocusOrder(planetID, AIFocusType.FOCUS_MINING) print "Changing planet focus for ID %s : %s from %s to %s "%(planetID, planet.name, oldFocus, AIFocusType.FOCUS_MINING ) continue newFocus=None if ( ratioRatio > 1.1 ): #needs industry if oldFocus == AIFocusType.FOCUS_INDUSTRY: continue else: newFocus = AIFocusType.FOCUS_INDUSTRY elif ( ratioRatio < 0.91 ): if oldFocus == AIFocusType.FOCUS_RESEARCH: continue else: newFocus = AIFocusType.FOCUS_RESEARCH if newFocus: #pp -= planet.currentMeterValue(fo.meterType.targetIndustry) #rp -= planet.currentMeterValue(fo.meterType.targetResearch) fo.issueChangeFocusOrder(planetID, newFocus) iChanges += 1 #pp += planet.currentMeterValue(fo.meterType.targetIndustry) #rp += planet.currentMeterValue(fo.meterType.targetResearch) print "Changing planet focus for ID %s : %s from %s to %s "%(planetID, planet.name, oldFocus, newFocus ) timer.append( time() ) #end if doResourceTiming and __timerEntries==__timerEntries2: times = [timer[i] - timer[i-1] for i in range(1, len(timer) ) ] timeFmt = "%30s: %8d msec " print "ResourcesAI Time Requirements:" for mod, modTime in zip(__timerEntries, times): print timeFmt%((30*' '+mod)[-30:], int(1000*modTime)) if resourceTimerFile: print "len times: %d ; len entries: %d "%(len(times), len(__timerEntries)) resourceTimerFile.write( __timerFileFmt%tuple( [ fo.currentTurn() ]+map(lambda x: int(1000*x), times )) +'\n') resourceTimerFile.flush()
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 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