def setGasGiantsResourceFocus(): "change resource focus of gas giants from farming to research" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) newFocus = AIFocusType.FOCUS_RESEARCH for planetID in empirePlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planet.type == fo.planetType.gasGiant and 'GRO_ORBIT_FARMING' in empire.availableTechs and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus)
def setAsteroidsResourceFocus(): "change resource focus of asteroids from farming to mining" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) newFocus = AIFocusType.FOCUS_INDUSTRY for planetID in empirePlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planet.type == fo.planetType.asteroids and 'GRO_ORBIT_FARMING' in empire.availableTechs and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus)
def bake_future_focus(self, pid, focus, update=True): """Set the focus and moves it from the raw list to the baked list of planets. pid -- pid focus -- future focus to use update -- If update is True then the meters of the raw planets will be updated. If the planet's change of focus will have a global effect (growth, production or research special), then update should be True. Return success or failure """ info = self.raw_planet_info.get(pid) success = bool(info is not None and (info.current_focus == focus or (focus in info.planet.availableFoci and fo.issueChangeFocusOrder(pid, focus)))) if success: if update and info.current_focus != focus: universe = fo.getUniverse() universe.updateMeterEstimates(self.raw_planet_info.keys()) industry_target = info.planet.currentMeterValue(fo.meterType.targetIndustry) research_target = info.planet.currentMeterValue(fo.meterType.targetResearch) info.possible_output[focus] = (industry_target, research_target) info.future_focus = focus self.baked_planet_info[pid] = self.raw_planet_info.pop(pid) return success
def bake_future_focus(self, pid, focus, update=True): """Set the focus and moves it from the raw list to the baked list of planets. pid -- pid focus -- future focus to use update -- If update is True then the meters of the raw planets will be updated. If the planet's change of focus will have a global effect (growth, production or research special), then update should be True. Return success or failure """ pinfo = self.raw_planet_info.get(pid) success = bool(pinfo is not None and (pinfo.current_focus == focus or (focus in pinfo.planet.availableFoci and fo.issueChangeFocusOrder(pid, focus)))) if success: if update and pinfo.current_focus != focus: universe = fo.getUniverse() universe.updateMeterEstimates(self.raw_planet_info.keys()) industry_target = pinfo.planet.currentMeterValue( fo.meterType.targetIndustry) research_target = pinfo.planet.currentMeterValue( fo.meterType.targetResearch) pinfo.possible_output[focus] = (industry_target, research_target) pinfo.future_focus = focus self.baked_planet_info[pid] = self.raw_planet_info.pop(pid) return success
def getResourceTargetTotals(empirePlanetIDs, planetMap):#+ 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) newTargets.setdefault(pid, {})[IFocus] = ( itarget, rtarget ) #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) newTargets.setdefault(pid, {})[RFocus] = ( itarget, rtarget ) #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 setGeneralPlanetResourceFocus(): "set resource focus of planets except capitalID, asteroids, and gas giants" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) capitalID = [empire.capitalID] asteroids = PlanetUtilsAI.getTypePlanetEmpireOwned(fo.planetType.asteroids) gasGiants = PlanetUtilsAI.getTypePlanetEmpireOwned(fo.planetType.gasGiant) generalPlanetIDs = list(set(empirePlanetIDs) - (set(capitalID)|set(asteroids)|set(gasGiants))) topPriority = topResourcePriority() fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs) if topPriority == AIPriorityType.PRIORITY_RESOURCE_FOOD: newFocus = AIFocusType.FOCUS_FARMING for planetID in generalPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_MINERALS: newFocus = AIFocusType.FOCUS_MINING for planetID in generalPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID in fleetSupplyablePlanetIDs and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_PRODUCTION: newFocus = AIFocusType.FOCUS_INDUSTRY for planetID in generalPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID in fleetSupplyablePlanetIDs and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_RESEARCH: newFocus = AIFocusType.FOCUS_RESEARCH for planetID in generalPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID in fleetSupplyablePlanetIDs and focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus) else: focus = AIFocusType.FOCUS_FARMING if focus in planet.availableFoci: fo.issueChangeFocusOrder(planetID, focus)
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 calculate_planet_infos(self, pids): """ Calculates for each possible focus the target output of each planet and stores it in planet info It excludes baked planets from consideration. Note: The results will not be strictly correct if any planets have global effects """ # TODO this function depends on the specific rule that off-focus meter value are always the minimum value universe = fo.getUniverse() unbaked_pids = [ pid for pid in pids if pid not in self.baked_planet_info ] planet_infos = [(pid, self.all_planet_info[pid], self.all_planet_info[pid].planet) for pid in unbaked_pids] for pid, pinfo, planet in planet_infos: if INDUSTRY in planet.availableFoci and planet.focus != INDUSTRY: fo.issueChangeFocusOrder( pid, INDUSTRY) # may not be able to take, but try universe.updateMeterEstimates(unbaked_pids) for pid, pinfo, planet in planet_infos: industry_target = planet.currentMeterValue( fo.meterType.targetIndustry) research_target = planet.currentMeterValue( fo.meterType.targetResearch) if planet.focus == INDUSTRY: pinfo.possible_output[INDUSTRY] = (industry_target, research_target) pinfo.possible_output[GROWTH] = research_target else: pinfo.possible_output[INDUSTRY] = (0, 0) pinfo.possible_output[GROWTH] = 0 if RESEARCH in planet.availableFoci and planet.focus != RESEARCH: fo.issueChangeFocusOrder( pid, RESEARCH) # may not be able to take, but try universe.updateMeterEstimates(unbaked_pids) for pid, pinfo, planet in planet_infos: industry_target = planet.currentMeterValue( fo.meterType.targetIndustry) research_target = planet.currentMeterValue( fo.meterType.targetResearch) if planet.focus == RESEARCH: pinfo.possible_output[RESEARCH] = (industry_target, research_target) pinfo.possible_output[GROWTH] = (industry_target, pinfo.possible_output[GROWTH]) else: pinfo.possible_output[RESEARCH] = (0, 0) pinfo.possible_output[GROWTH] = (0, pinfo.possible_output[GROWTH]) if pinfo.planet.availableFoci and pinfo.current_focus != planet.focus: fo.issueChangeFocusOrder( pid, pinfo.current_focus) # put it back to what it was universe.updateMeterEstimates(unbaked_pids) # Protection focus will give the same off-focus Industry and Research targets as Growth Focus for pid, pinfo, planet in planet_infos: pinfo.possible_output[PROTECTION] = pinfo.possible_output[GROWTH]
def _fill_data_dicts(planet_ids): universe = fo.getUniverse() newTargets.clear() currentFocus.clear() currentOutput.clear() planets = [(pid, planetMap[pid]) for pid in planet_ids] for pid, planet in planets: currentFocus[pid] = planet.focus 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(planet_ids) for pid, planet in planets: 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(planet_ids) for pid, planet in planets: can_focus = 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 can_focus and currentFocus[pid] != planet.focus: fo.issueChangeFocusOrder( pid, currentFocus[pid]) # put it back to what it was universe.updateMeterEstimates(planet_ids) # Protection focus will give the same off-focus Industry and Research targets as Growth Focus for pid, planet in planets: newTargets[pid][PFocus] = newTargets[pid][GFocus]
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: 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) fo.issueChangeFocusOrder(pid, IFocus) #may not be able to take, but try universe.updateMeterEstimates(empirePlanetIDs) for pid in empirePlanetIDs: 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 ) fo.issueChangeFocusOrder(pid, RFocus) #may not be able to take, but try universe.updateMeterEstimates(empirePlanetIDs) for pid in empirePlanetIDs: 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 currentFocus[pid] != RFocus: fo.issueChangeFocusOrder(pid, currentFocus[pid]) #put it back to what it was universe.updateMeterEstimates(empirePlanetIDs) return targetPP, targetRP
def _fill_data_dicts(planet_ids): universe = fo.getUniverse() newTargets.clear() currentFocus.clear() currentOutput.clear() planets = [(pid, planetMap[pid]) for pid in planet_ids] for pid, planet in planets: currentFocus[pid] = planet.focus 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(planet_ids) for pid, planet in planets: 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(planet_ids) for pid, planet in planets: can_focus = 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 can_focus and currentFocus[pid] != planet.focus: fo.issueChangeFocusOrder(pid, currentFocus[pid]) # put it back to what it was universe.updateMeterEstimates(planet_ids) # Protection focus will give the same off-focus Industry and Research targets as Growth Focus for pid, planet in planets: newTargets[pid][PFocus] = newTargets[pid][GFocus]
def calculate_planet_infos(self, pids): """ Calculates for each possible focus the target output of each planet and stores it in planet info It excludes baked planets from consideration. Note: The results will not be strictly correct if any planets have global effects """ # TODO this function depends on the specific rule that off-focus meter value are always the minimum value universe = fo.getUniverse() unbaked_pids = [pid for pid in pids if pid not in self.baked_planet_info] planet_infos = [(pid, self.all_planet_info[pid], self.all_planet_info[pid].planet) for pid in unbaked_pids] for pid, info, planet in planet_infos: if INDUSTRY in planet.availableFoci and planet.focus != INDUSTRY: fo.issueChangeFocusOrder(pid, INDUSTRY) # may not be able to take, but try universe.updateMeterEstimates(unbaked_pids) for pid, info, planet in planet_infos: industry_target = planet.currentMeterValue(fo.meterType.targetIndustry) research_target = planet.currentMeterValue(fo.meterType.targetResearch) if planet.focus == INDUSTRY: info.possible_output[INDUSTRY] = (industry_target, research_target) info.possible_output[GROWTH] = research_target else: info.possible_output[INDUSTRY] = (0, 0) info.possible_output[GROWTH] = 0 if RESEARCH in planet.availableFoci and planet.focus != RESEARCH: fo.issueChangeFocusOrder(pid, RESEARCH) # may not be able to take, but try universe.updateMeterEstimates(unbaked_pids) for pid, info, planet in planet_infos: industry_target = planet.currentMeterValue(fo.meterType.targetIndustry) research_target = planet.currentMeterValue(fo.meterType.targetResearch) if planet.focus == RESEARCH: info.possible_output[RESEARCH] = (industry_target, research_target) info.possible_output[GROWTH] = (industry_target, info.possible_output[GROWTH]) else: info.possible_output[RESEARCH] = (0, 0) info.possible_output[GROWTH] = (0, info.possible_output[GROWTH]) if info.planet.availableFoci and info.current_focus != planet.focus: fo.issueChangeFocusOrder(pid, info.current_focus) # put it back to what it was universe.updateMeterEstimates(unbaked_pids) # Protection focus will give the same off-focus Industry and Research targets as Growth Focus for pid, info, planet in planet_infos: info.possible_output[PRODUCTION] = info.possible_output[GROWTH]
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 generateResourcesOrders(): "generate resources focus orders" # get the highest resource priorities universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID ownedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) capitalID = PlanetUtilsAI.getCapitalID() print "Resources Management:" print "" print "Resource Priorities:" resourcePriorities = {} for priorityType in getAIPriorityResourceTypes(): resourcePriorities[priorityType] = foAI.foAIstate.getPriority(priorityType) sortedPriorities = resourcePriorities.items() sortedPriorities.sort(lambda x,y: cmp(x[1], y[1]), reverse=True) topPriority = -1 for evaluationPair in sortedPriorities: if topPriority < 0: topPriority = evaluationPair[0] print " ID|Score: " + str(evaluationPair) print " Top Resource Priority: " + str(topPriority) if topPriority == AIPriorityType.PRIORITY_RESOURCE_FOOD: newFocus = AIFocusType.FOCUS_FARMING print " New Resource Focus: " + str(newFocus) for planetID in ownedPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID == capitalID and newFocus in planet.availableFoci: print " Capital ID: " + str(planetID) + " Resource Focus: " + str(newFocus) fo.issueChangeFocusOrder(planetID, newFocus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_MINERALS: newFocus = AIFocusType.FOCUS_MINING print " Top Resource Focus: " + str(newFocus) for planetID in ownedPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID == capitalID and newFocus in planet.availableFoci: print " Capital ID: " + str(planetID) + " Resource Focus: " + str(newFocus) fo.issueChangeFocusOrder(planetID, newFocus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_PRODUCTION: newFocus = AIFocusType.FOCUS_INDUSTRY print " New Resource Focus: " + str(newFocus) for planetID in ownedPlanetIDs: planet = universe.getPlanet(planetID) focus = newFocus if planetID == capitalID and newFocus in planet.availableFoci: print " Capital ID: " + str(planetID) + " Resource Focus: " + str(newFocus) fo.issueChangeFocusOrder(planetID, newFocus) elif topPriority == AIPriorityType.PRIORITY_RESOURCE_RESEARCH: newFocus = AIFocusType.FOCUS_RESEARCH print " New Resource Focus: " + str(newFocus) # what is the focus of available resource centers? print "" print "Planet Resources Foci:" print "" print " Empire Owned planetIDs:" + str(ownedPlanetIDs) for planetID in ownedPlanetIDs: planet = universe.getPlanet(planetID) planetPopulation = planet.currentMeterValue(fo.meterType.population) print " ID: " + str(planetID) + " Name: " + str(planet.name) + " Type: " + str(planet.type) + " Size: " + str(planet.size) + " Focus: " + str(planet.focus) + " Species: " + str(planet.speciesName) + " Population: " + str(planetPopulation)
def bake_future_focus(self, pid, focus, update=True, force=False): """Set the focus and moves it from the raw list to the baked list of planets. pid -- pid focus -- future focus to use update -- If update is True then the meters of the raw planets will be updated. If the planet's change of focus will have a global effect (growth, production or research special), then update should be True. Return success or failure """ pinfo = self.raw_planet_info.get(pid) if not pinfo: return False if (focus == INDUSTRY or focus == RESEARCH) and not force: idx = 0 if focus == INDUSTRY else 1 # check for influence instead focus_gain = pinfo.possible_output[focus][ idx] - pinfo.possible_output[INFLUENCE][idx] influence_gain = pinfo.possible_output[INFLUENCE][ 2] - pinfo.possible_output[focus][2] debug( f"{pinfo.planet.name} current: {_focus_name(pinfo.current_focus)}, requested: {_focus_name(focus)}, " f"requested_gain: {focus_gain}, influence_gain: {influence_gain}" ) if influence_gain * self.priority[2] > focus_gain * self.priority[ idx]: debug(f"Choosing influence over {_focus_name(focus)}." f" {influence_gain:.2f} * {self.priority[2]:.1f}" f" > {focus_gain:.2f} * {self.priority[idx]:.1f}") focus = INFLUENCE last_turn = fo.currentTurn() if ( # define idx constants for accessing these tuples focus != PROTECTION and focus != pinfo.current_focus and policy_is_adopted(bureaucracy) and pinfo.current_output[2] + 0.2 < pinfo.possible_output[pinfo.current_focus][2] and pinfo.planet.LastTurnColonized != last_turn and pinfo.planet.LastTurnConquered != last_turn): # avoid going down too much by repeated focus changes while having bureaucracy info( "Avoid focus change on %s due to bureaucracy. IPprod: current=%.2f, target=%.2f", pinfo.planet.name, pinfo.current_output[2], pinfo.possible_output[pinfo.current_focus][2], ) return False success = bool(pinfo.current_focus == focus or (focus in pinfo.planet.availableFoci and fo.issueChangeFocusOrder(pid, focus))) if success: if update and pinfo.current_focus != focus: universe = fo.getUniverse() universe.updateMeterEstimates(self.raw_planet_info.keys()) industry_target = pinfo.planet.currentMeterValue( fo.meterType.targetIndustry) research_target = pinfo.planet.currentMeterValue( fo.meterType.targetResearch) influence_target = pinfo.planet.currentMeterValue( fo.meterType.targetInfluence) pinfo.possible_output[focus] = (industry_target, research_target, influence_target) pinfo.future_focus = focus self.baked_planet_info[pid] = self.raw_planet_info.pop(pid) return success
def calculate_planet_infos(self, pids): """Calculates for each possible focus the target output of each planet and stores it in planet info It excludes baked planets from consideration. Note: The results will not be strictly correct if any planets have global effects """ # TODO this function depends on the specific rule that off-focus meter value are always the minimum value universe = fo.getUniverse() unbaked_pids = [ pid for pid in pids if pid not in self.baked_planet_info ] planet_infos = [(pid, self.all_planet_info[pid], self.all_planet_info[pid].planet) for pid in unbaked_pids] for pid, pinfo, planet in planet_infos: if INDUSTRY in planet.availableFoci and planet.focus != INDUSTRY: fo.issueChangeFocusOrder( pid, INDUSTRY) # may not be able to take, but try def merge(po1, po2): """merge two partially determined possible_outputs""" return ( po1[0] or po2[0], po1[1] or po2[1], po1[2] or po2[2], ) universe.updateMeterEstimates(unbaked_pids) for pid, pinfo, planet in planet_infos: po = pinfo.possible_output industry_target = planet.currentMeterValue( fo.meterType.targetIndustry) research_target = planet.currentMeterValue( fo.meterType.targetResearch) influence_target = planet.currentMeterValue( fo.meterType.targetInfluence) if planet.focus == INDUSTRY: # each focus only affects its own meter po[INDUSTRY] = (industry_target, research_target, influence_target) po[GROWTH] = (0, research_target, influence_target) po[INFLUENCE] = (0, research_target, 0) else: po[INDUSTRY] = (0, 0, 0) po[GROWTH] = (0, 0, 0) po[INFLUENCE] = (0, 0, 0) if RESEARCH in planet.availableFoci and planet.focus != RESEARCH: fo.issueChangeFocusOrder( pid, RESEARCH) # may not be able to take, but try universe.updateMeterEstimates(unbaked_pids) for pid, pinfo, planet in planet_infos: po = pinfo.possible_output industry_target = planet.currentMeterValue( fo.meterType.targetIndustry) research_target = planet.currentMeterValue( fo.meterType.targetResearch) influence_target = planet.currentMeterValue( fo.meterType.targetInfluence) if planet.focus == RESEARCH: po[RESEARCH] = (industry_target, research_target, influence_target) po[GROWTH] = merge(po[GROWTH], (industry_target, 0, influence_target)) po[INFLUENCE] = merge(po[INFLUENCE], (industry_target, 0, 0)) else: po[RESEARCH] = (0, 0, 0) if INFLUENCE in planet.availableFoci and planet.focus != INFLUENCE: fo.issueChangeFocusOrder( pid, INFLUENCE) # may not be able to take, but try universe.updateMeterEstimates(unbaked_pids) for pid, pinfo, planet in planet_infos: po = pinfo.possible_output industry_target = planet.currentMeterValue( fo.meterType.targetIndustry) research_target = planet.currentMeterValue( fo.meterType.targetResearch) influence_target = planet.currentMeterValue( fo.meterType.targetInfluence) if planet.focus == INFLUENCE: po[INFLUENCE] = (industry_target, research_target, influence_target) else: po[INFLUENCE] = (0, 0, 0) if pinfo.planet.availableFoci and pinfo.current_focus != planet.focus: fo.issueChangeFocusOrder( pid, pinfo.current_focus) # put it back to what it was universe.updateMeterEstimates(unbaked_pids) # Protection focus will give the same off-focus Industry and Research targets as Growth Focus for pid, pinfo, planet in planet_infos: po = pinfo.possible_output po[PROTECTION] = po[GROWTH] for focus in [INDUSTRY, RESEARCH, INFLUENCE, PROTECTION]: debug( "Resource output of planet %s for focus %s is %f/%f/%f", pinfo.planet, focus, po[focus][0], po[focus][1], po[focus][2], )
def set_planet_resource_foci(): """set resource focus of planets """ newFoci = {} print "\n============================" print "Collecting info to assess Planet Focus Changes\n" universe = fo.getUniverse() empire = fo.getEmpire() currentTurn = fo.currentTurn() # set the random seed (based on galaxy seed, empire ID and current turn) # for game-reload consistency freq = min(3, (max(5, currentTurn - 80)) / 4.0) ** (1.0 / 3) if not (limitAssessments and (abs(currentTurn - lastFociCheck[0]) < 1.5 * freq) and (random.random() < 1.0 / freq)): lastFociCheck[0] = currentTurn resource_timer.start("getPlanets") empirePlanetIDs = list(PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)) resource_timer.start("Filter") resource_timer.start("Priority") # TODO: take into acct splintering of resource groups # fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs # fleetSupplyablePlanetIDs = PlanetUtilsAI.get_planets_in__systems_ids(fleetSupplyableSystemIDs) ppPrio = foAI.foAIstate.get_priority(AIPriorityType.PRIORITY_RESOURCE_PRODUCTION) rpPrio = foAI.foAIstate.get_priority(AIPriorityType.PRIORITY_RESOURCE_RESEARCH) priorityRatio = float(rpPrio) / (ppPrio + 0.0001) resource_timer.start("Shuffle") # not supporting Growth for general planets until also adding code to make sure would actually benefit # shuffle(generalPlanetIDs) resource_timer.start("Targets") planets = map(universe.getPlanet, empirePlanetIDs) planetMap.clear() planetMap.update(zip(empirePlanetIDs, planets)) if useGrowth: for metab, metabIncPop in ColonisationAI.empire_metabolisms.items(): for special in [aspec for aspec in AIDependencies.metabolismBoostMap.get(metab, []) if aspec in ColonisationAI.available_growth_specials]: rankedPlanets = [] for pid in ColonisationAI.available_growth_specials[special]: planet = planetMap[pid] cur_focus = planet.focus pop = planet.currentMeterValue(fo.meterType.population) if (pop > metabIncPop - 2 * planet.size) or (GFocus not in planet.availableFoci): # not enough benefit to lose local production, or can't put growth focus here continue for special2 in ["COMPUTRONIUM_SPECIAL"]: if special2 in planet.specials: break else: # didn't have any specials that would override interest in growth special print "Considering Growth Focus for %s (%d) with special %s; planet has pop %.1f and %s metabolism incremental pop is %.1f" % ( planet.name, pid, special, pop, metab, metabIncPop) if cur_focus == GFocus: pop -= 4 # discourage changing current focus to minimize focus-changing penalties rankedPlanets.append((pop, pid, cur_focus)) if not rankedPlanets: continue rankedPlanets.sort() print "Considering Growth Focus choice for special %s; possible planet pop, id pairs are %s" % (metab, rankedPlanets) for spSize, spPID, cur_focus in rankedPlanets: # index 0 should be able to set focus, but just in case... result = 1 if cur_focus != GFocus: result = fo.issueChangeFocusOrder(spPID, GFocus) if result == 1: newFoci[spPID] = GFocus if spPID in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index(spPID)] print "%s focus of planet %s (%d) at Growth Focus" % (["set", "left"][cur_focus == GFocus], planetMap[spPID].name, spPID) break else: print "failed setting focus of planet %s (%d) at Growth Focus; focus left at %s" % (planetMap[spPID].name, spPID, planetMap[spPID].focus) already_have_comp_moon = False for pid in empirePlanetIDs: planet = planetMap[pid] if "COMPUTRONIUM_SPECIAL" in planet.specials and RFocus in planet.availableFoci and not already_have_comp_moon: curFocus = planet.focus newFoci[pid] = RFocus result = 0 if curFocus != RFocus: result = fo.issueChangeFocusOrder(pid, RFocus) if result == 1: universe.updateMeterEstimates(empirePlanetIDs) if curFocus == RFocus or result == 1: already_have_comp_moon = True print "%s focus of planet %s (%d) (with Computronium Moon) at Research Focus" % (["set", "left"][curFocus == RFocus], planetMap[pid].name, pid) if pid in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index(pid)] continue if ((([bld.buildingTypeName for bld in map(universe.getObject, planet.buildingIDs) if bld.buildingTypeName in ["BLD_CONC_CAMP", "BLD_CONC_CAMP_REMNANT"]] != []) or ([ccspec for ccspec in planet.specials if ccspec in ["CONC_CAMP_MASTER_SPECIAL", "CONC_CAMP_SLAVE_SPECIAL"]] != [])) and IFocus in planet.availableFoci): curFocus = planet.focus newFoci[pid] = IFocus result = 0 if curFocus != IFocus: result = fo.issueChangeFocusOrder(pid, IFocus) if result == 1: print ("Tried setting %s for Concentration Camp planet %s (%d) with species %s and current focus %s, got result %d and focus %s" % (newFoci[pid], planet.name, pid, planet.speciesName, curFocus, result, planetMap[pid].focus)) universe.updateMeterEstimates(empirePlanetIDs) if (result != 1) or planetMap[pid].focus != IFocus: newplanet = universe.getPlanet(pid) print ("Error: Failed setting %s for Concentration Camp planet %s (%d) with species %s and current focus %s, but new planet copy shows %s" % (newFoci[pid], planetMap[pid].name, pid, planetMap[pid].speciesName, planetMap[pid].focus, newplanet.focus)) if curFocus == IFocus or result == 1: print "%s focus of planet %s (%d) (with Concentration Camps/Remnants) at Industry Focus" % (["set", "left"][curFocus == IFocus], planetMap[pid].name, pid) if pid in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index(pid)] continue # pp, rp = get_resource_target_totals(empirePlanetIDs, planetMap) pp, rp = get_resource_target_totals(planetMap.keys()) for pid in empirePlanetIDs: planet = planetMap[pid] if PFocus in planet.availableFoci and assess_protection_focus(pid): curFocus = planet.focus newFoci[pid] = PFocus result = 0 if curFocus != PFocus: result = fo.issueChangeFocusOrder(pid, PFocus) if result == 1: print ("Tried setting %s for planet %s (%d) with species %s and current focus %s, got result %d and focus %s" % (newFoci[pid], planet.name, pid, planet.speciesName, curFocus, result, planet.focus)) universe.updateMeterEstimates(empirePlanetIDs) if (result != 1) or planet.focus != PFocus: newplanet = universe.getPlanet(pid) print ("Error: Failed setting %s for planet %s (%d) with species %s and current focus %s, but new planet copy shows %s" % (newFoci[pid], planet.name, pid, planet.speciesName, planet.focus, newplanet.focus)) if curFocus == PFocus or result == 1: print "%s focus of planet %s (%d) at Protection(Defense) Focus" % (["set", "left"][curFocus == PFocus], planet.name, pid) if pid in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index(pid)] continue print "\n-----------------------------------------" print "Making Planet Focus Change Determinations\n" ratios = [] # for each planet, calculate RP:PP value ratio at which industry/Mining focus and research focus would have the same total value, & sort by that # include a bias to slightly discourage changing foci curTargetPP = 0.001 curTargetRP = 0.001 resource_timer.start("Loop") # loop has_force = tech_is_complete("CON_FRC_ENRG_STRC") preset_ids = set(planetMap.keys()) - set(empirePlanetIDs) ctPP0, ctRP0 = 0, 0 for pid in preset_ids: nPP, nRP = newTargets.get(pid, {}).get(planetMap[pid].focus, [0, 0]) curTargetPP += nPP curTargetRP += nRP iPP, iRP = newTargets.get(pid, {}).get(IFocus, [0, 0]) ctPP0 += iPP ctRP0 += iRP id_set = set(empirePlanetIDs) for adj_round in [1, 2, 3, 4]: maxi_ratio = ctRP0 / max(0.01, ctPP0) # should only change between rounds 1 and 2 for pid in list(id_set): if adj_round == 1: # tally max Industry iPP, iRP = newTargets.get(pid, {}).get(IFocus, [0, 0]) ctPP0 += iPP ctRP0 += iRP continue II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] CI, CR = currentOutput[pid][IFocus], currentOutput[pid][RFocus] research_penalty = (currentFocus[pid] != RFocus) # calculate factor F at which II + F * IR == RI + F * RR =====> F = ( II-RI ) / (RR-IR) thisFactor = (II - RI) / max(0.01, RR - IR) # don't let denominator be zero for planets where focus doesn't change RP planet = planetMap[pid] if adj_round == 2: # take research at planets with very cheap research if (maxi_ratio < priorityRatio) and (curTargetRP < priorityRatio * ctPP0) and (thisFactor <= 1.0): curTargetPP += RI curTargetRP += RR newFoci[pid] = RFocus id_set.discard(pid) continue if adj_round == 3: # take research at planets where can do reasonable balance if has_force or (foAI.foAIstate.aggression < fo.aggression.aggressive) or (curTargetRP >= priorityRatio * ctPP0): continue pop = planet.currentMeterValue(fo.meterType.population) t_pop = planet.currentMeterValue(fo.meterType.targetPopulation) # if AI is aggressive+, and this planet in range where temporary Research focus can get an additional RP at cost of 1 PP, and still need some RP, then do it if pop < t_pop - 5: continue if (CI > II + 8) or (((RR > II) or ((RR - CR) >= 1 + 2 * research_penalty)) and ((RR - IR) >= 3) and ((CR - IR) >= 0.7 * ((II - CI) * (1 + 0.1 * research_penalty)))): curTargetPP += CI - 1 - research_penalty curTargetRP += CR + 1 newFoci[pid] = RFocus id_set.discard(pid) continue # adj_round == 4 assume default IFocus curTargetPP += II # icurTargets initially calculated by Industry focus, which will be our default focus curTargetRP += IR newFoci[pid] = IFocus ratios.append((thisFactor, pid)) ratios.sort() printedHeader = False fociMap = {IFocus: "Industry", RFocus: "Research", MFocus: "Mining", GFocus: "Growth", PFocus: "Defense"} gotAlgo = tech_is_complete("LRN_ALGO_ELEGANCE") for ratio, pid in ratios: do_research = False # (newFoci[pid]==RFocus) if (priorityRatio < (curTargetRP / (curTargetPP + 0.0001))) and not do_research: # we have enough RP if ratio < 1.1 and foAI.foAIstate.aggression > fo.aggression.cautious: # but wait, RP is still super cheap relative to PP, maybe will take more RP if priorityRatio < 1.5 * (curTargetRP / (curTargetPP + 0.0001)): # yeah, really a glut of RP, stop taking RP break else: # RP not super cheap & we have enough, stop taking it break II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] # if currentFocus[pid] == MFocus: # II = max( II, newTargets[pid][MFocus][0] ) if do_research or (gotAlgo and ( (ratio > 2.0 and curTargetPP < 15) or (ratio > 2.5 and curTargetPP < 25 and II > 5) or (ratio > 3.0 and curTargetPP < 40 and II > 5) or (ratio > 4.0 and curTargetPP < 100 and II > 10) or ((curTargetRP + RR - IR) / max(0.001, curTargetPP - II + RI) > 2 * priorityRatio))): # we already have algo elegance and more RP would be too expensive, or overkill if not printedHeader: printedHeader = True print "Rejecting further Research Focus choices as too expensive:" print "%34s|%20s|%15s |%15s|%15s |%15s |%15s" % (" Planet ", " current RP/PP ", " current target RP/PP ", "current Focus ", " rejectedFocus ", " rejected target RP/PP ", "rejected RP-PP EQF") oldFocus = currentFocus[pid] cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][RFocus] otPP, otRP = newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP = newTargets[pid].get(RFocus, (0, 0)) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f | %.2f" % (pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[RFocus], ntRP, ntPP, ratio) continue # RP is getting too expensive, but might be willing to still allocate from a planet with less PP to lose # if planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0: #only set to research if pop won't die out newFoci[pid] = RFocus curTargetRP += (RR - IR) curTargetPP -= (II - RI) print "============================" print "Planet Focus Assignments to achieve target RP/PP ratio of %.2f from current ratio of %.2f ( %.1f / %.1f )" % (priorityRatio, rp / (pp + 0.0001), rp, pp) print "Max Industry assignments would result in target RP/PP ratio of %.2f ( %.1f / %.1f )" % (ctRP0 / (ctPP0 + 0.0001), ctRP0, ctPP0) print "-------------------------------------" print "%34s|%20s|%15s |%15s|%15s |%15s " % (" Planet ", " current RP/PP ", " current target RP/PP ", "current Focus ", " newFocus ", " new target RP/PP ") totalChanged = 0 for id_set in empirePlanetIDs, preset_ids: for pid in id_set: canFocus = planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) > 0 oldFocus = currentFocus[pid] newFocus = newFoci.get(pid, IFocus) cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][RFocus] otPP, otRP = newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP = otPP, otRP if newFocus != oldFocus and newFocus in planetMap[pid].availableFoci: # planetMap[pid].focus totalChanged += 1 if newFocus != planetMap[pid].focus: result = fo.issueChangeFocusOrder(pid, newFocus) if result == 1: ntPP, ntRP = newTargets[pid].get(newFocus, (0, 0)) else: print "Trouble changing focus of planet %s (%d) to %s" % (planetMap[pid].name, pid, newFocus) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f " % (pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[newFocus], ntRP, ntPP) print "-------------------------------------" print "-------------------------------------" print "Final Ratio Target (turn %4d) RP/PP : %.2f ( %.1f / %.1f ) after %d Focus changes" % (fo.currentTurn(), curTargetRP / (curTargetPP + 0.0001), curTargetRP, curTargetPP, totalChanged) resource_timer.end() aPP, aRP = empire.productionPoints, empire.resourceProduction(fo.resourceType.research) # Next string used in charts. Don't modify it! print "Current Output (turn %4d) RP/PP : %.2f ( %.1f / %.1f )" % (fo.currentTurn(), aRP / (aPP + 0.0001), aRP, aPP) print "------------------------" print "ResourcesAI Time Requirements:"
def set_planet_resource_foci(): """set resource focus of planets """ newFoci = {} print "\n============================" print "Collecting info to assess Planet Focus Changes\n" universe = fo.getUniverse() empire = fo.getEmpire() currentTurn = fo.currentTurn() # set the random seed (based on galaxy seed, empire ID and current turn) # for game-reload consistency freq = min(3, (max(5, currentTurn - 80)) / 4.0)**(1.0 / 3) if not (limitAssessments and (abs(currentTurn - lastFociCheck[0]) < 1.5 * freq) and (random.random() < 1.0 / freq)): lastFociCheck[0] = currentTurn resource_timer.start("getPlanets") empirePlanetIDs = list( PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)) resource_timer.start("Filter") resource_timer.start("Priority") # TODO: take into acct splintering of resource groups # fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs # fleetSupplyablePlanetIDs = PlanetUtilsAI.get_planets_in__systems_ids(fleetSupplyableSystemIDs) ppPrio = foAI.foAIstate.get_priority( AIPriorityType.PRIORITY_RESOURCE_PRODUCTION) rpPrio = foAI.foAIstate.get_priority( AIPriorityType.PRIORITY_RESOURCE_RESEARCH) priorityRatio = float(rpPrio) / (ppPrio + 0.0001) resource_timer.start("Shuffle") # not supporting Growth for general planets until also adding code to make sure would actually benefit # shuffle(generalPlanetIDs) resource_timer.start("Targets") planets = map(universe.getPlanet, empirePlanetIDs) planetMap.clear() planetMap.update(zip(empirePlanetIDs, planets)) if useGrowth: for metab, metabIncPop in ColonisationAI.empire_metabolisms.items( ): for special in [ aspec for aspec in AIDependencies.metabolismBoostMap.get( metab, []) if aspec in ColonisationAI.available_growth_specials ]: rankedPlanets = [] for pid in ColonisationAI.available_growth_specials[ special]: planet = planetMap[pid] cur_focus = planet.focus pop = planet.currentMeterValue(fo.meterType.population) if (pop > metabIncPop - 2 * planet.size) or ( GFocus not in planet.availableFoci ): # not enough benefit to lose local production, or can't put growth focus here continue for special2 in ["COMPUTRONIUM_SPECIAL"]: if special2 in planet.specials: break else: # didn't have any specials that would override interest in growth special print "Considering Growth Focus for %s (%d) with special %s; planet has pop %.1f and %s metabolism incremental pop is %.1f" % ( planet.name, pid, special, pop, metab, metabIncPop) if cur_focus == GFocus: pop -= 4 # discourage changing current focus to minimize focus-changing penalties rankedPlanets.append((pop, pid, cur_focus)) if not rankedPlanets: continue rankedPlanets.sort() print "Considering Growth Focus choice for special %s; possible planet pop, id pairs are %s" % ( metab, rankedPlanets) for spSize, spPID, cur_focus in rankedPlanets: # index 0 should be able to set focus, but just in case... result = 1 if cur_focus != GFocus: result = fo.issueChangeFocusOrder(spPID, GFocus) if result == 1: newFoci[spPID] = GFocus if spPID in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index( spPID)] print "%s focus of planet %s (%d) at Growth Focus" % ( ["set", "left"][cur_focus == GFocus], planetMap[spPID].name, spPID) break else: print "failed setting focus of planet %s (%d) at Growth Focus; focus left at %s" % ( planetMap[spPID].name, spPID, planetMap[spPID].focus) for pid in empirePlanetIDs: planet = planetMap[pid] if "COMPUTRONIUM_SPECIAL" in planet.specials: # TODO: ensure only one (extremely rarely needed) curFocus = planet.focus if RFocus not in planet.availableFoci: continue newFoci[pid] = RFocus result = 0 if curFocus != RFocus: result = fo.issueChangeFocusOrder(pid, RFocus) if result == 1: universe.updateMeterEstimates(empirePlanetIDs) if curFocus == RFocus or result == 1: print "%s focus of planet %s (%d) (with Computronium Moon) at Research Focus" % ( ["set", "left" ][curFocus == RFocus], planetMap[pid].name, pid) if pid in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index(pid)] elif (([ bld.buildingTypeName for bld in map(universe.getObject, planet.buildingIDs) if bld.buildingTypeName in ["BLD_CONC_CAMP", "BLD_CONC_CAMP_REMNANT"] ] != []) or ([ ccspec for ccspec in planet.specials if ccspec in ["CONC_CAMP_MASTER_SPECIAL", "CONC_CAMP_SLAVE_SPECIAL"] ] != [])): if IFocus not in planet.availableFoci: continue curFocus = planet.focus newFoci[pid] = IFocus result = 0 if curFocus != IFocus: result = fo.issueChangeFocusOrder(pid, IFocus) if result == 1: print( "Tried setting %s for Concentration Camp planet %s (%d) with species %s and current focus %s, got result %d and focus %s" % (newFoci[pid], planet.name, pid, planet.speciesName, curFocus, result, planetMap[pid].focus)) universe.updateMeterEstimates(empirePlanetIDs) if (result != 1) or planetMap[pid].focus != IFocus: newplanet = universe.getPlanet(pid) print( "Error: Failed setting %s for Concentration Camp planet %s (%d) with species %s and current focus %s, but new planet copy shows %s" % (newFoci[pid], planetMap[pid].name, pid, planetMap[pid].speciesName, planetMap[pid].focus, newplanet.focus)) if curFocus == IFocus or result == 1: print "%s focus of planet %s (%d) (with Concentration Camps/Remnants) at Industry Focus" % ( ["set", "left" ][curFocus == IFocus], planetMap[pid].name, pid) if pid in empirePlanetIDs: del empirePlanetIDs[empirePlanetIDs.index(pid)] # pp, rp = get_resource_target_totals(empirePlanetIDs, planetMap) pp, rp = get_resource_target_totals(planetMap.keys()) print "\n-----------------------------------------" print "Making Planet Focus Change Determinations\n" ratios = [] # for each planet, calculate RP:PP value ratio at which industry/Mining focus and research focus would have the same total value, & sort by that # include a bias to slightly discourage changing foci curTargetPP = 0.001 curTargetRP = 0.001 resource_timer.start("Loop") # loop has_force = tech_is_complete("CON_FRC_ENRG_STRC") preset_ids = set(planetMap.keys()) - set(empirePlanetIDs) ctPP0, ctRP0 = 0, 0 for pid in preset_ids: nPP, nRP = newTargets.get(pid, {}).get(planetMap[pid].focus, [0, 0]) curTargetPP += nPP curTargetRP += nRP iPP, iRP = newTargets.get(pid, {}).get(IFocus, [0, 0]) ctPP0 += iPP ctRP0 += iRP id_set = set(empirePlanetIDs) for adj_round in [1, 2, 3, 4]: maxi_ratio = ctRP0 / max( 0.01, ctPP0) # should only change between rounds 1 and 2 for pid in list(id_set): if adj_round == 1: # tally max Industry iPP, iRP = newTargets.get(pid, {}).get(IFocus, [0, 0]) ctPP0 += iPP ctRP0 += iRP continue II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] CI, CR = currentOutput[pid][IFocus], currentOutput[pid][RFocus] research_penalty = (currentFocus[pid] != RFocus) # calculate factor F at which II + F * IR == RI + F * RR =====> F = ( II-RI ) / (RR-IR) thisFactor = (II - RI) / max( 0.01, RR - IR ) # don't let denominator be zero for planets where focus doesn't change RP planet = planetMap[pid] if adj_round == 2: # take research at planets with very cheap research if (maxi_ratio < priorityRatio) and ( curTargetRP < priorityRatio * ctPP0) and (thisFactor <= 1.0): curTargetPP += RI curTargetRP += RR newFoci[pid] = RFocus id_set.discard(pid) continue if adj_round == 3: # take research at planets where can do reasonable balance if has_force or (foAI.foAIstate.aggression < fo.aggression.aggressive) or ( curTargetRP >= priorityRatio * ctPP0): continue pop = planet.currentMeterValue(fo.meterType.population) t_pop = planet.currentMeterValue( fo.meterType.targetPopulation) # if AI is aggressive+, and this planet in range where temporary Research focus can get an additional RP at cost of 1 PP, and still need some RP, then do it if pop < t_pop - 5: continue if (CI > II + 8) or (((RR > II) or ( (RR - CR) >= 1 + 2 * research_penalty)) and ((RR - IR) >= 3) and ((CR - IR) >= 0.7 * ((II - CI) * (1 + 0.1 * research_penalty)))): curTargetPP += CI - 1 - research_penalty curTargetRP += CR + 1 newFoci[pid] = RFocus id_set.discard(pid) continue # adj_round == 4 assume default IFocus curTargetPP += II # icurTargets initially calculated by Industry focus, which will be our default focus curTargetRP += IR newFoci[pid] = IFocus ratios.append((thisFactor, pid)) ratios.sort() printedHeader = False fociMap = { IFocus: "Industry", RFocus: "Research", MFocus: "Mining", GFocus: "Growth" } gotAlgo = tech_is_complete("LRN_ALGO_ELEGANCE") for ratio, pid in ratios: do_research = False # (newFoci[pid]==RFocus) if (priorityRatio < (curTargetRP / (curTargetPP + 0.0001)) ) and not do_research: # we have enough RP if ratio < 1.1 and foAI.foAIstate.aggression > fo.aggression.cautious: # but wait, RP is still super cheap relative to PP, maybe will take more RP if priorityRatio < 1.5 * ( curTargetRP / (curTargetPP + 0.0001) ): # yeah, really a glut of RP, stop taking RP break else: # RP not super cheap & we have enough, stop taking it break II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] # if currentFocus[pid] == MFocus: # II = max( II, newTargets[pid][MFocus][0] ) if do_research or ( gotAlgo and ((ratio > 2.0 and curTargetPP < 15) or (ratio > 2.5 and curTargetPP < 25 and II > 5) or (ratio > 3.0 and curTargetPP < 40 and II > 5) or (ratio > 4.0 and curTargetPP < 100 and II > 10) or ((curTargetRP + RR - IR) / max(0.001, curTargetPP - II + RI) > 2 * priorityRatio)) ): # we already have algo elegance and more RP would be too expensive, or overkill if not printedHeader: printedHeader = True print "Rejecting further Research Focus choices as too expensive:" print "%34s|%20s|%15s |%15s|%15s |%15s |%15s" % ( " Planet ", " current RP/PP ", " current target RP/PP ", "current Focus ", " rejectedFocus ", " rejected target RP/PP ", "rejected RP-PP EQF") oldFocus = currentFocus[pid] cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][ RFocus] otPP, otRP = newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP = newTargets[pid].get(RFocus, (0, 0)) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f | %.2f" % ( pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[RFocus], ntRP, ntPP, ratio) continue # RP is getting too expensive, but might be willing to still allocate from a planet with less PP to lose # if planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0: #only set to research if pop won't die out newFoci[pid] = RFocus curTargetRP += (RR - IR) curTargetPP -= (II - RI) print "============================" print "Planet Focus Assignments to achieve target RP/PP ratio of %.2f from current ratio of %.2f ( %.1f / %.1f )" % ( priorityRatio, rp / (pp + 0.0001), rp, pp) print "Max Industry assignments would result in target RP/PP ratio of %.2f ( %.1f / %.1f )" % ( ctRP0 / (ctPP0 + 0.0001), ctRP0, ctPP0) print "-------------------------------------" print "%34s|%20s|%15s |%15s|%15s |%15s " % ( " Planet ", " current RP/PP ", " current target RP/PP ", "current Focus ", " newFocus ", " new target RP/PP ") totalChanged = 0 for id_set in empirePlanetIDs, preset_ids: for pid in id_set: canFocus = planetMap[pid].currentMeterValue( fo.meterType.targetPopulation) > 0 oldFocus = currentFocus[pid] newFocus = newFoci.get(pid, IFocus) cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][ RFocus] otPP, otRP = newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP = otPP, otRP if newFocus != oldFocus and newFocus in planetMap[ pid].availableFoci: # planetMap[pid].focus totalChanged += 1 if newFocus != planetMap[pid].focus: result = fo.issueChangeFocusOrder(pid, newFocus) if result == 1: ntPP, ntRP = newTargets[pid].get(newFocus, (0, 0)) else: print "Trouble changing focus of planet %s (%d) to %s" % ( planetMap[pid].name, pid, newFocus) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f " % ( pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[newFocus], ntRP, ntPP) print "-------------------------------------" print "-------------------------------------" print "Final Ratio Target (turn %4d) RP/PP : %.2f ( %.1f / %.1f ) after %d Focus changes" % ( fo.currentTurn(), curTargetRP / (curTargetPP + 0.0001), curTargetRP, curTargetPP, totalChanged) resource_timer.end() aPP, aRP = empire.productionPoints, empire.resourceProduction( fo.resourceType.research) # Next string used in charts. Don't modify it! print "Current Output (turn %4d) RP/PP : %.2f ( %.1f / %.1f )" % ( fo.currentTurn(), aRP / (aPP + 0.0001), aRP, aPP) print "------------------------" print "ResourcesAI Time Requirements:"
def setPlanetResourceFoci(): "set resource focus of planets except capitalID, asteroids, and gas giants" global __timerFile print "\n============================" print "Collecting info to assess Planet Focus Changes\n" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID currentTurn = fo.currentTurn() freq = (1.0 + currentTurn/4.0)**(1.0/3) if random() > 1.0/freq: timer = 6*[time()] else: timer= [ time() ] # getPlanets empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) timer.append( time() ) #filter timer.append( time() ) #Priority #TODO: take into acct splintering of resource groups #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(rpPrio)/(ppPrio+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() planets = map(universe.getPlanet, empirePlanetIDs) planetMap = dict( zip( empirePlanetIDs, planets)) print "\n-----------------------------------------" print "Making Planet Focus Change Determinations\n" ratios = [] #for each planet, calculate RP:PP value ratio at which industry/Mining focus and research focus would have the same total value, & sort by that # include a bias to slightly discourage changing foci curTargetPP = 0 curTargetRP = 0 newFoci = {} timer.append( time() ) #loop hasForce = empire.getTechStatus("CON_FRC_ENRG_STRC") == fo.techStatus.complete for pid in newTargets: II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] if currentFocus[pid] == MFocus: II = max( II, newTargets[pid][MFocus][0] ) curTargetPP += II #icurTargets initially calculated by Industry focus, which will be our default focus curTargetRP += IR newFoci[pid] = IFocus if foAI.foAIstate.aggression < 4: if currentFocus[pid] in [ IFocus, MFocus] : II += min( 2, II /4.0 ) elif currentFocus[pid] == RFocus: RR += min( 2, RR/4.0 ) #calculate factor F at which II + F * RI == RI + F * RR =====> F = ( II-RI ) / (RR-IR) thisFactor = ( II-RI ) / max( 0.01, RR-IR) # don't let denominator be zero for planets where focus doesn't change RP if foAI.foAIstate.aggression >3: if currentOutput[pid][ IFocus] > II +RI - RR: thisFactor = min(thisFactor, 1.0 + thisFactor/10.0 ) ratios.append( (thisFactor, pid ) ) ctPP0 = curTargetPP ctRP0 = curTargetRP ratios.sort() printedHeader=False fociMap={IFocus:"Industry", RFocus:"Research", MFocus:"Mining", GFocus:"Growth"} gotAlgo = empire.getTechStatus("LRN_ALGO_ELEGANCE") == fo.techStatus.complete for ratio, pid in ratios: if priorityRatio < ( curTargetRP/ (curTargetPP + 0.0001)) : #we have enough RP if ratio < 1.1 and foAI.foAIstate.aggression >1 : #but wait, RP is still super cheap relative to PP, maybe will take more RP if priorityRatio < 1.5* ( curTargetRP/ (curTargetPP + 0.0001)) : #yeah, really a glut of RP, stop taking RP break else: #RP not super cheap & we have enough, stop taking it break II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] if currentFocus[pid] == MFocus: II = max( II, newTargets[pid][MFocus][0] ) if gotAlgo and ( (ratio > 2.0 and curTargetPP < 15) or (ratio > 2.5 and curTargetPP < 25 and II > 5) or (ratio > 3.0 and curTargetPP < 40 and II > 5) or (ratio > 4.0 and curTargetPP < 100 and II > 10) or ( (curTargetRP+RR-IR)/max(0.001, curTargetPP - II+RI) > 2* priorityRatio )): # we already have algo elegance and more RP would be too expensive, or overkill if not printedHeader: printedHeader=True print "Rejecting further Research Focus choices as too expensive:" print "%34s|%20s|%15s |%15s|%15s |%15s |%15s"%(" Planet ", " current RP/PP ", " current target RP/PP ", "current Focus "," rejectedFocus ", " rejected target RP/PP ", "rejected RP-PP EQF") oldFocus=currentFocus[pid] cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][RFocus] otPP, otRP= newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP= newTargets[pid].get(RFocus, (0, 0)) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f | %.2f"%(pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[RFocus] , ntRP, ntPP , ratio) continue # RP is getting too expensive, but might be willing to still allocate from a planet with less PP to lose newFoci[pid] = RFocus curTargetRP += (RR-IR) curTargetPP -= (II-RI) print "============================" print "Planet Focus Assignments to achieve target RP/PP ratio of %.2f from current ratio of %.2f ( %.1f / %.1f )"%(priorityRatio, rp/(pp+0.0001), rp, pp) print "Max Industry assignments would result in target RP/PP ratio of %.2f ( %.1f / %.1f )"%( ctRP0/ (ctPP0 + 0.0001), ctRP0, ctPP0 ) print "-------------------------------------" print "%34s|%20s|%15s |%15s|%15s |%15s "%(" Planet ", " current RP/PP ", " current target RP/PP ", "current Focus "," newFocus ", " new target RP/PP ") totalChanged=0 for pid in newTargets: oldFocus=currentFocus[pid] changeFocus=False newFocus = newFoci[pid] cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][RFocus] if newFocus==RFocus and oldFocus!=RFocus: changeFocus = True elif newFocus == IFocus: if ( MFocus in planetMap[pid].availableFoci ) and ( newTargets[pid].setdefault(MFocus, (25, IR))[0] > newTargets[pid][IFocus][0]): newFocus=MFocus if newFocus !=oldFocus: changeFocus = True else: pass #not supporting growth focus yet if changeFocus: totalChanged+=1 fo.issueChangeFocusOrder(pid, newFocus) otPP, otRP= newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP= newTargets[pid].get(newFocus, (0, 0)) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f "%(pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[newFocus] , ntRP, ntPP ) print "-------------------------------------\nFinal Ratio Target (turn %4d) RP/PP : %.2f ( %.1f / %.1f ) after %d Focus changes"%( fo.currentTurn(), curTargetRP/ (curTargetPP + 0.0001), curTargetRP, curTargetPP , totalChanged) aPP, aRP = empire.productionPoints, empire.resourceProduction(fo.resourceType.research) print "Current Output (turn %4d) RP/PP : %.2f ( %.1f / %.1f )"%(fo.currentTurn(), aRP/ (aPP + 0.0001), aRP, aPP ), "\n------------------------" 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 setPlanetResourceFoci(): #+ "set resource focus of planets " global __timerFile print "\n============================" print "Collecting info to assess Planet Focus Changes\n" universe = fo.getUniverse() empire = fo.getEmpire() empireID = empire.empireID currentTurn = fo.currentTurn() freq = min(3, ( max(5, currentTurn-120) )/4.0)**(1.0/3) if ( abs(currentTurn - lastFociCheck[0] ) <1.5*freq) and ( random() < 1.0/freq ) : timer = 6*[time()] else: lastFociCheck[0]=currentTurn timer= [ time() ] # getPlanets empirePlanetIDs = list( PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) ) timer.append( time() ) #filter timer.append( time() ) #Priority #TODO: take into acct splintering of resource groups #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(rpPrio)/(ppPrio+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 planets = map(universe.getPlanet, empirePlanetIDs) planetMap = dict( zip( empirePlanetIDs, planets)) if useGrowth: for metab, metabIncPop in ColonisationAI.empireMetabolisms.items(): for special in [aspec for aspec in AIDependencies.metabolimBoostMap.get(metab, []) if aspec in ColonisationAI.availableGrowthSpecials]: rankedPlanets=[] for pid in ColonisationAI.availableGrowthSpecials[special]: planet = planetMap[pid] pop = planet.currentMeterValue(fo.meterType.population) if (pop > metabIncPop - planet.size) or (GFocus not in planet.availableFoci): #not enough benefit to lose local production, or can't put growth focus here continue for special2 in [ "COMPUTRONIUM_SPECIAL" ]: if special2 in planet.specials: break else: #didn't have any specials that would override interest in growth special print "Considering Growth Focus for %s (%d) with special %s; planet has pop %.1f and %s metabolism incremental pop is %.1f"%( planet.name, pid, special, pop, metab, metabIncPop) rankedPlanets.append( (pop, pid) ) if rankedPlanets == []: continue rankedPlanets.sort() print "Considering Growth Focus choice for special %s; possible planet pop, id pairs are %s"%(metab, rankedPlanets) for spSize, spPID in rankedPlanets: #index 0 should be able to set focus, but just in case... result = 1 curFocus = planet.focus if curFocus != GFocus: result = fo.issueChangeFocusOrder(spPID, GFocus) if result == 1: if spPID in empirePlanetIDs: del empirePlanetIDs[ empirePlanetIDs.index( spPID ) ] print "%s focus of planet %s (%d) at Growth Focus"%( ["set", "left" ][ curFocus == GFocus ] , planetMap[spPID].name, spPID) break else: print "failed setting focus of planet %s (%d) at Growth Focus; focus left at %s"%( planetMap[spPID].name, spPID, planetMap[spPID].focus) pp, rp = getResourceTargetTotals(empirePlanetIDs, planetMap) print "\n-----------------------------------------" print "Making Planet Focus Change Determinations\n" ratios = [] #for each planet, calculate RP:PP value ratio at which industry/Mining focus and research focus would have the same total value, & sort by that # include a bias to slightly discourage changing foci curTargetPP = 0.001 curTargetRP = 0.001 newFoci = {} timer.append( time() ) #loop hasForce = empire.getTechStatus("CON_FRC_ENRG_STRC") == fo.techStatus.complete for pid in newTargets: II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] CI, CR = currentOutput[pid][ IFocus], currentOutput[pid][ RFocus] #consider straddling balance range within which 1RP costs 1PP if True and (foAI.foAIstate.aggression >= fo.aggression.aggressive): if (CR<RR) and ( (CR-IR) >= (II-CI) ) and (priorityRatio > ( (curTargetRP+CR+1)/ max(0.001, curTargetPP +CI -1))): curTargetPP += CI -1 # curTargetRP += CR+1 newFoci[pid] = RFocus continue curTargetPP += II #icurTargets initially calculated by Industry focus, which will be our default focus curTargetRP += IR newFoci[pid] = IFocus #if foAI.foAIstate.aggression < fo.aggression.maniacal: # if currentFocus[pid] in [ IFocus, MFocus] : # II += min( 2, II /4.0 ) # elif currentFocus[pid] == RFocus: # RR += min( 2, RR/4.0 ) #calculate factor F at which II + F * RI == RI + F * RR =====> F = ( II-RI ) / (RR-IR) thisFactor = ( II-RI ) / max( 0.01, RR-IR) # don't let denominator be zero for planets where focus doesn't change RP if foAI.foAIstate.aggression >fo.aggression.aggressive: if currentOutput[pid][ IFocus] > II +RI - RR: thisFactor = min(thisFactor, 1.0 + thisFactor/10.0 ) ratios.append( (thisFactor, pid ) ) ctPP0 = curTargetPP ctRP0 = curTargetRP ratios.sort() printedHeader=False fociMap={IFocus:"Industry", RFocus:"Research", MFocus:"Mining", GFocus:"Growth"} gotAlgo = empire.getTechStatus("LRN_ALGO_ELEGANCE") == fo.techStatus.complete for ratio, pid in ratios: if priorityRatio < ( curTargetRP/ (curTargetPP + 0.0001)) : #we have enough RP if ratio < 1.1 and foAI.foAIstate.aggression >fo.aggression.cautious : #but wait, RP is still super cheap relative to PP, maybe will take more RP if priorityRatio < 1.5* ( curTargetRP/ (curTargetPP + 0.0001)) : #yeah, really a glut of RP, stop taking RP break else: #RP not super cheap & we have enough, stop taking it break II, IR = newTargets[pid][IFocus] RI, RR = newTargets[pid][RFocus] #if currentFocus[pid] == MFocus: # II = max( II, newTargets[pid][MFocus][0] ) if gotAlgo and ( (ratio > 2.0 and curTargetPP < 15) or (ratio > 2.5 and curTargetPP < 25 and II > 5) or (ratio > 3.0 and curTargetPP < 40 and II > 5) or (ratio > 4.0 and curTargetPP < 100 and II > 10) or ( (curTargetRP+RR-IR)/max(0.001, curTargetPP - II+RI) > 2* priorityRatio )): # we already have algo elegance and more RP would be too expensive, or overkill if not printedHeader: printedHeader=True print "Rejecting further Research Focus choices as too expensive:" print "%34s|%20s|%15s |%15s|%15s |%15s |%15s"%(" Planet ", " current RP/PP ", " current target RP/PP ", "current Focus "," rejectedFocus ", " rejected target RP/PP ", "rejected RP-PP EQF") oldFocus=currentFocus[pid] cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][RFocus] otPP, otRP= newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP= newTargets[pid].get(RFocus, (0, 0)) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f | %.2f"%(pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[RFocus] , ntRP, ntPP , ratio) continue # RP is getting too expensive, but might be willing to still allocate from a planet with less PP to lose if planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0: #only set to research if pop won't die out newFoci[pid] = RFocus curTargetRP += (RR-IR) curTargetPP -= (II-RI) print "============================" print "Planet Focus Assignments to achieve target RP/PP ratio of %.2f from current ratio of %.2f ( %.1f / %.1f )"%(priorityRatio, rp/(pp+0.0001), rp, pp) print "Max Industry assignments would result in target RP/PP ratio of %.2f ( %.1f / %.1f )"%( ctRP0/ (ctPP0 + 0.0001), ctRP0, ctPP0 ) print "-------------------------------------" print "%34s|%20s|%15s |%15s|%15s |%15s "%(" Planet ", " current RP/PP ", " current target RP/PP ", "current Focus "," newFocus ", " new target RP/PP ") totalChanged=0 for pid in newTargets: canFocus= planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0 oldFocus=currentFocus[pid] newFocus = newFoci[pid] cPP, cRP = currentOutput[pid][IFocus], currentOutput[pid][RFocus] if newFocus!= planetMap[pid].focus and newFocus in planetMap[pid].availableFoci: totalChanged+=1 result = fo.issueChangeFocusOrder(pid, newFocus) if result != 1: print "Trouble changing focus of planet %s (%d) to %s"%(planetMap[pid].name, pid, newFocus) otPP, otRP= newTargets[pid].get(oldFocus, (0, 0)) ntPP, ntRP= newTargets[pid].get(newFocus, (0, 0)) print "pID (%3d) %22s | c: %5.1f / %5.1f | cT: %5.1f / %5.1f | cF: %8s | nF: %8s | cT: %5.1f / %5.1f "%(pid, planetMap[pid].name, cRP, cPP, otRP, otPP, fociMap.get(oldFocus, 'unknown'), fociMap[newFocus] , ntRP, ntPP ) print "-------------------------------------\nFinal Ratio Target (turn %4d) RP/PP : %.2f ( %.1f / %.1f ) after %d Focus changes"%( fo.currentTurn(), curTargetRP/ (curTargetPP + 0.0001), curTargetRP, curTargetPP , totalChanged) aPP, aRP = empire.productionPoints, empire.resourceProduction(fo.resourceType.research) print "Current Output (turn %4d) RP/PP : %.2f ( %.1f / %.1f )"%(fo.currentTurn(), aRP/ (aPP + 0.0001), aRP, aPP ), "\n------------------------" 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 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()