Esempio n. 1
0
    def issue_order(self):
        if not super(OrderResupply, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            # if self.order_type == AIFleetOrderType.ORDER_MOVE:
            #     dest_id = system_id
            # else:
            # if self.order_type == AIFleetOrderType.ORDER_REPAIR:
            #     fo.issueAggressionOrder(fleet_id, False)
            start_id = FleetUtilsAI.get_fleet_system(fleet)
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
                fleet_id, self.ORDER_NAME,
                PlanetUtilsAI.sys_name_ids([dest_id]),
                PlanetUtilsAI.sys_name_ids([system_id]))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    foAI.foAIstate.needsEmergencyExploration.remove(system_id)
            self.order_issued = True
Esempio n. 2
0
 def __border_exploration_update(self):
     universe = fo.getUniverse()
     exploration_center = PlanetUtilsAI.get_capital_sys_id()
     # a bad state probably from an old savegame, or else empire has lost (or almost has)
     if exploration_center == INVALID_ID:
         exploration_center = self.__origin_home_system_id
     ExplorationAI.graph_flags.clear()
     if fo.currentTurn() < 50:
         print "-------------------------------------------------"
         print "Border Exploration Update (relative to %s)" % (
             PlanetUtilsAI.sys_name_ids([exploration_center, INVALID_ID])[0])
         print "-------------------------------------------------"
     if self.visBorderSystemIDs == {INVALID_ID}:
         self.visBorderSystemIDs.clear()
         self.visBorderSystemIDs.add(exploration_center)
     for sys_id in list(self.visBorderSystemIDs):  # This set is modified during iteration.
         if fo.currentTurn() < 50:
             print "Considering border system %s" % (PlanetUtilsAI.sys_name_ids([sys_id, INVALID_ID])[0])
         ExplorationAI.follow_vis_system_connections(sys_id, exploration_center)
     newly_explored = ExplorationAI.update_explored_systems()
     nametags = []
     for sys_id in newly_explored:
         newsys = universe.getSystem(sys_id)
         # an explored system *should* always be able to be gotten
         nametags.append("ID:%4d -- %-20s" % (sys_id, (newsys and newsys.name) or "name unknown"))
     if newly_explored:
         print "-------------------------------------------------"
         print "Newly explored systems:\n%s" % "\n".join(nametags)
         print "-------------------------------------------------"
Esempio n. 3
0
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

    fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
    fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs)

    # get competitor planets
    exploredSystemIDs = empire.exploredSystemIDs
    exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs)

    allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(exploredPlanetIDs)
    # print "All Owned and Populated PlanetIDs: " + str(allOwnedPlanetIDs)

    empireOwnedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    # print "Empire Owned PlanetIDs:            " + str(empireOwnedPlanetIDs)

    competitorPlanetIDs = list(set(allOwnedPlanetIDs) - set(empireOwnedPlanetIDs))
    print "Competitor PlanetIDs:              " + str(competitorPlanetIDs)

    print ""
    print "Invasion Targeted SystemIDs:       " + str(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(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(competitorPlanetIDs) - set(invasionTargetedPlanetIDs))
    # print "Evaluated PlanetIDs:               " + str(evaluatedPlanetIDs)

    evaluatedPlanets = assignInvasionValues(evaluatedPlanetIDs, AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire)

    sortedPlanets = evaluatedPlanets.items()
    sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)

    print ""
    print "Invadable planetIDs:"
    for evaluationPair in sortedPlanets:
        print "    ID|Score: " + str(evaluationPair)

    # export opponent planets for other AI modules
    AIstate.opponentPlanetIDs = sortedPlanets
Esempio n. 4
0
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)
Esempio n. 5
0
def calculateMilitaryPriority():
    "calculates the demand for military ships by military targeted systems"
    global unmetThreat

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    capitalID = PlanetUtilsAI.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)
Esempio n. 6
0
def calculateMilitaryPriority():
    "calculates the demand for military ships by military targeted systems"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    capitalID = PlanetUtilsAI.getCapital()
    if capitalID:
        homeworld = universe.getPlanet(capitalID)
    else:
        return 0# no capitol (not even a capitol-in-the-making), means can't produce any ships
    allottedInvasionTargets = 1+ int(fo.currentTurn()/25)
    targetPlanetIDs =  [pid for pid, pscore, trp in AIstate.invasionTargets[:allottedInvasionTargets] ] + [pid for pid,  pscore in foAI.foAIstate.colonisablePlanetIDs[:allottedColonyTargets]  ] + [pid for pid,  pscore in foAI.foAIstate.colonisableOutpostIDs[:allottedColonyTargets]  ]
    
    mySystems = set( AIstate.popCtrSystemIDs ).union( AIstate.outpostSystemIDs   )
    targetSystems = set( PlanetUtilsAI.getSystems(targetPlanetIDs)  )
    
    curShipRating = ProductionAI.curBestMilShipRating()
    cSRR = curShipRating**0.5

    unmetThreat = 0.0
    currentTurn=fo.currentTurn()
    shipsNeeded=0
    for sysID in mySystems.union(targetSystems) :
        status=foAI.foAIstate.systemStatus.get( sysID,  {} )
        myAttack,  myHealth =0, 0
        for fid in status.get('myfleets', []) :
            rating= foAI.foAIstate.fleetStatus.get(fid,  {}).get('rating', {})
            myAttack += rating.get('attack', 0)
            myHealth += rating.get('health', 0)
        myRating = myAttack*myHealth
        baseMonsterThreat = status.get('monsterThreat', 0)
        if currentTurn>200:
            monsterThreat = baseMonsterThreat
        elif currentTurn>100:
            if baseMonsterThreat <2000:
                monsterThreat = baseMonsterThreat
            else:
                monsterThreat = 2000 + (currentTurn/100.0 - 1) *(baseMonsterThreat-2000)
        else:
            monsterThreat = 0
            
        threatRoot = status.get('fleetThreat', 0)**0.5 + status.get('planetThreat', 0)**0.5 + monsterThreat**0.5
        if sysID in mySystems:
             threatRoot +=  (0.3* status.get('neighborThreat', 0))**0.5   
        else:
             threatRoot +=  (0.1* status.get('neighborThreat', 0))**0.5   
        threat = threatRoot**2
        unmetThreat += max( 0,  threat - myRating )
        shipsNeeded += math.ceil( max(0,   (threatRoot/cSRR)- (myRating/curShipRating)**0.5 ) )
        
    #militaryPriority = int( 40 + max(0,  75*unmetThreat / curShipRating) )  
    militaryPriority = int( 40 + max(0,  75*shipsNeeded) )  
    #print "Calculating Military Priority:  40 + 75 * unmetThreat/curShipRating \n\t  Priority: %d    \t unmetThreat  %.0f        curShipRating: %.0f"%(militaryPriority,  unmetThreat,  curShipRating)
    print "Calculating Military Priority:  40 + 75 * shipsNeeded \n\t  Priority: %d   \t shipsNeeded %d   \t unmetThreat  %.0f        curShipRating: %.0f"%(militaryPriority, shipsNeeded,   unmetThreat,  curShipRating)
    return max( militaryPriority,  0)
Esempio n. 7
0
def getColonyFleets():
    # get colony fleets
    allColonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)
    AIstate.colonyFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allColonyFleetIDs)

    # get supplyable systems
    empire = fo.getEmpire()
    universe = fo.getUniverse()
    capitalID = empire.capitalID
    homeworld = universe.getPlanet(capitalID)
    speciesName = homeworld.speciesName
    species = fo.getSpecies(speciesName)

    fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
    fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs)
    print "    fleetSupplyablePlanetIDs:" + str(fleetSupplyablePlanetIDs)

    # get planets
    systemIDs = foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_EXPLORED)
    planetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(systemIDs)

    removeAlreadyOwnedPlanetIDs(planetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION)
    removeAlreadyOwnedPlanetIDs(planetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST)

    evaluatedPlanets = assignColonisationValues(planetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION, fleetSupplyablePlanetIDs, species, empire)
    removeLowValuePlanets(evaluatedPlanets)

    sortedPlanets = evaluatedPlanets.items()
    sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)

    print "Colonisable planets:"
    for evaluationPair in sortedPlanets:
        print "    ID|Score: " + str(evaluationPair)
    print ""

    # export planets for other AI modules
    AIstate.colonisablePlanetIDs = sortedPlanets

    # get outpost fleets
    allOutpostFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST)
    AIstate.outpostFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allOutpostFleetIDs)

    evaluatedOutposts = assignColonisationValues(planetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, fleetSupplyablePlanetIDs, species, empire)
    removeLowValuePlanets(evaluatedOutposts)

    sortedOutposts = evaluatedOutposts.items()
    sortedOutposts.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)

    print "Colonisable outposts:"
    for evaluationPair in sortedOutposts:
        print "    ID|Score: " + str(evaluationPair)
    print ""

    # export outposts for other AI modules
    AIstate.colonisableOutpostIDs = sortedOutposts
Esempio n. 8
0
def get_safe_path_leg_to_dest(fleet_id,  start_id,  dest_id):
    start_targ = AITarget.AITarget(AITargetType.TARGET_SYSTEM, start_id)
    dest_targ = AITarget.AITarget(AITargetType.TARGET_SYSTEM, dest_id)
    #TODO actually get a safe path
    this_path = canTravelToSystem(fleet_id, start_targ, dest_targ, fo.empireID(),  ensure_return=False)
    path_ids = [ targ.target_id for targ in this_path if targ.target_id != start_id] + [start_id]
    start_info = PlanetUtilsAI.sysNameIDs([start_id])
    dest_info = PlanetUtilsAI.sysNameIDs([dest_id])
    path_info = [ PlanetUtilsAI.sysNameIDs([sys_id]) for sys_id in path_ids]
    print "Fleet %d requested safe path leg from %s to %s,  found path %s"%(fleet_id,  start_info, dest_info ,  path_info)
    return path_ids[0]
Esempio n. 9
0
def get_safe_path_leg_to_dest(fleet_id, start_id, dest_id):
    start_targ = universe_object.System(start_id)
    dest_targ = universe_object.System(dest_id)
    # TODO actually get a safe path
    this_path = can_travel_to_system(fleet_id, start_targ, dest_targ, ensure_return=False)
    path_ids = [targ.id for targ in this_path if targ.id != start_id] + [start_id]
    start_info = PlanetUtilsAI.sys_name_ids([start_id])
    dest_info = PlanetUtilsAI.sys_name_ids([dest_id])
    path_info = [PlanetUtilsAI.sys_name_ids([sys_id]) for sys_id in path_ids]
    print "Fleet %d requested safe path leg from %s to %s, found path %s" % (fleet_id, ppstring(start_info), ppstring(dest_info), ppstring(path_info))
    return path_ids[0]
Esempio n. 10
0
def get_safe_path_leg_to_dest(fleet_id, start_id, dest_id):
    start_targ = universe_object.System(start_id)
    dest_targ = universe_object.System(dest_id)
    # TODO actually get a safe path
    this_path = can_travel_to_system(fleet_id, start_targ, dest_targ, ensure_return=False)
    path_ids = [targ.id for targ in this_path if targ.id != start_id] + [start_id]
    start_info = PlanetUtilsAI.sys_name_ids([start_id])
    dest_info = PlanetUtilsAI.sys_name_ids([dest_id])
    path_info = [PlanetUtilsAI.sys_name_ids([sys_id]) for sys_id in path_ids]
    print "Fleet %d requested safe path leg from %s to %s, found path %s" % (fleet_id, ppstring(start_info), ppstring(dest_info), ppstring(path_info))
    return path_ids[0]
Esempio n. 11
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
Esempio n. 12
0
 def __init__(self, status_only: bool = False):
     self._empire = fo.getEmpire()
     self._universe = fo.getUniverse()
     self._aistate = get_aistate()
     # resourceAvailable includes this turns production, but that is wrong for influence
     self._ip = self._empire.resourceAvailable(
         fo.resourceType.influence) - self._get_infl_prod()
     self._adopted = set(self._empire.adoptedPolicies)
     # When we continue a game in which we just adopted a policy, game state shows the policy as adopted,
     # but IP still unspent. Correct it here, then calculate anew whether we want to adopt it.
     if not status_only:
         for entry in self._empire.turnsPoliciesAdopted:
             if entry.data() == fo.currentTurn():
                 debug(f"reverting saved adopt {entry.key()}")
                 fo.issueDeadoptPolicyOrder(entry.key())
                 self._adopted.remove(entry.key())
     self._originally_adopted = copy(self._adopted)
     empire_owned_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire()
     self._populated_planet_ids = PlanetUtilsAI.get_populated_planet_ids(
         empire_owned_planet_ids)
     self._num_populated = len(self._populated_planet_ids)
     self._num_outposts = len(empire_owned_planet_ids) - self._num_populated
     self._max_turn_bureaucracy = self._calculate_max_turn_bureaucracy()
     self._centralization_cost = fo.getPolicy(centralization).adoptionCost()
     self._bureaucracy_cost = fo.getPolicy(bureaucracy).adoptionCost()
     self._wanted_ip = self._wanted_for_bureaucracy()
     self._adoptable = self._get_adoptable()
     self._available = set(self._empire.availablePolicies)
     self._rating_functions = {
         propaganda: lambda: 20 + self._rate_opinion(propaganda),
         algo_research: self._rate_algo_research,
         diversity: self._rate_diversity,
         artisans: self._rate_artisans,
         population: self._rate_population,
         # military policies are mostly chosen by opinion, plus some rule-of-thumb values
         allied_repair: lambda: self._rate_opinion(
             charge),  # no effect, unless we have allies...
         charge:
         lambda: 5 + self._rate_opinion(charge),  # A small bonus in battle
         scanning: lambda: 20 + self._rate_opinion(
             scanning),  # May help us detect ships and planets
         simplicity: lambda: 20 + self._rate_opinion(
             simplicity),  # Makes simple ships cheaper
         engineering: self._rate_engineering_corps,
         exploration: lambda: 10 + self._rate_opinion(
             exploration),  # may give a little research, speeds up scouts
         flanking: lambda: 5 + self._rate_opinion(
             flanking),  # A small bonus in battle
         recruitment: lambda: 15 + self._rate_opinion(
             recruitment),  # cheaper troop ships
     }
Esempio n. 13
0
    def refresh(self):
        """Turn start AIstate cleanup/refresh."""
        universe = fo.getUniverse()
        # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
        fleetsLostBySystem.clear()
        invasionTargets[:] = []
        exploration_center = PlanetUtilsAI.get_capital_sys_id()
        # a bad state probably from an old savegame, or else empire has lost (or almost has)
        if exploration_center == INVALID_ID:
            exploration_center = self.__origin_home_system_id

        for system_id, info in sorted(self.systemStatus.items()):
            self.systemStatus[system_id][
                'enemy_ship_count'] = 0  # clear now in prep for update_system_status()
        ExplorationAI.graph_flags.clear()
        if fo.currentTurn() < 50:
            print "-------------------------------------------------"
            print "Border Exploration Update (relative to %s)" % (
                PlanetUtilsAI.sys_name_ids([exploration_center, INVALID_ID
                                            ])[0])
            print "-------------------------------------------------"
        if self.visBorderSystemIDs == {INVALID_ID}:
            self.visBorderSystemIDs.clear()
            self.visBorderSystemIDs.add(exploration_center)
        for sys_id in list(self.visBorderSystemIDs
                           ):  # This set is modified during iteration.
            if fo.currentTurn() < 50:
                print "Considering border system %s" % (
                    PlanetUtilsAI.sys_name_ids([sys_id, INVALID_ID])[0])
            ExplorationAI.follow_vis_system_connections(
                sys_id, exploration_center)
        newly_explored = ExplorationAI.update_explored_systems()
        nametags = []
        for sys_id in newly_explored:
            newsys = universe.getSystem(sys_id)
            # an explored system *should* always be able to be gotten
            nametags.append("ID:%4d -- %-20s" %
                            (sys_id,
                             (newsys and newsys.name) or "name unknown"))
        if newly_explored:
            print "-------------------------------------------------"
            print "Newly explored systems:\n%s" % "\n".join(nametags)
            print "-------------------------------------------------"
        # cleanup fleet roles
        # self.update_fleet_locs()
        self.__clean_fleet_roles()
        self.__clean_fleet_missions(FleetUtilsAI.get_empire_fleet_ids())
        print "Fleets lost by system: %s" % fleetsLostBySystem
        self.update_system_status()
Esempio n. 14
0
def avail_mil_needing_repair(mil_fleet_ids,
                             split_ships=False,
                             on_mission=False):
    """returns tuple of lists-- ( ids_needing_repair, ids_not )"""
    fleet_buckets = [[], []]
    universe = fo.getUniverse()
    cutoff = [0.70, 0.25][on_mission]
    for fleet_id in mil_fleet_ids:
        fleet = universe.getFleet(fleet_id)
        ship_buckets = [[], []]
        ships_cur_health = [0, 0]
        ships_max_health = [0, 0]
        for ship_id in fleet.shipIDs:
            this_ship = universe.getShip(ship_id)
            cur_struc = this_ship.currentMeterValue(fo.meterType.structure)
            max_struc = this_ship.currentMeterValue(fo.meterType.maxStructure)
            ship_ok = cur_struc >= cutoff * max_struc
            ship_buckets[ship_ok].append(ship_id)
            ships_cur_health[ship_ok] += cur_struc
            ships_max_health[ship_ok] += max_struc
        this_sys_id = (fleet.nextSystemID != -1
                       and fleet.nextSystemID) or fleet.systemID
        fleet_ok = (sum(ships_cur_health) >= cutoff * sum(ships_max_health))
        local_status = foAI.foAIstate.systemStatus.get(this_sys_id, {})
        my_local_rating = combine_ratings(
            local_status.get('mydefenses', {}).get('overall', 0),
            local_status.get('myFleetRating', 0))
        needed_here = local_status.get(
            'totalThreat',
            0) > 0  # TODO: assess if remaining other forces are sufficient
        safely_needed = needed_here and my_local_rating > local_status.get(
            'totalThreat', 0)  # TODO: improve both assessment prongs
        if not fleet_ok:
            if safely_needed:
                print "Fleet %d at %s needs repair but deemed safely needed to remain for defense" % (
                    fleet_id,
                    ppstring(PlanetUtilsAI.sys_name_ids([fleet.systemID])))
            else:
                if needed_here:
                    print "Fleet %d at %s needed present for combat, but is damaged and deemed unsafe to remain." % (
                        fleet_id,
                        ppstring(PlanetUtilsAI.sys_name_ids([fleet.systemID])))
                    print "\t my_local_rating: %.1f ; threat: %.1f" % (
                        my_local_rating, local_status.get('totalThreat', 0))
                print "Selecting fleet %d at %s for repair" % (
                    fleet_id,
                    ppstring(PlanetUtilsAI.sys_name_ids([fleet.systemID])))
        fleet_buckets[fleet_ok or safely_needed].append(fleet_id)
    return fleet_buckets
def avail_mil_needing_repair(mil_fleet_ids, split_ships=False, on_mission=False):
    """returns tuple of lists-- ( ids_needing_repair, ids_not )"""
    fleet_buckets = [[], []]
    universe = fo.getUniverse()
    cutoff = [0.70, 0.25][on_mission]
    for fleet_id in mil_fleet_ids:
        fleet = universe.getFleet(fleet_id)
        ship_buckets = [[], []]
        ships_cur_health = [0, 0]
        ships_max_health = [0, 0]
        safely_needed = False
        for ship_id in fleet.shipIDs:
            this_ship = universe.getShip(ship_id)
            cur_struc = this_ship.currentMeterValue(fo.meterType.structure)
            max_struc = this_ship.currentMeterValue(fo.meterType.maxStructure)
            ship_ok = cur_struc >= cutoff * max_struc
            ship_buckets[ship_ok].append(ship_id)
            ships_cur_health[ship_ok] += cur_struc
            ships_max_health[ship_ok] += max_struc
        thisSysID = (fleet.nextSystemID != -1 and fleet.nextSystemID) or fleet.systemID
        fleet_ok = sum(ships_cur_health) >= cutoff * sum(ships_max_health)
        local_status = foAI.foAIstate.systemStatus.get(thisSysID, {})
        my_local_rating = local_status.get("mydefenses", {}).get("overall", 0) + local_status.get("myFleetRating", 0)
        needed_here = local_status.get("totalThreat", 0) > 0  # TODO: assess if remaining other forces are sufficient
        safely_needed = needed_here and my_local_rating > local_status.get(
            "totalThreat", 0
        )  # TODO: improve both assessment prongs
        if not fleet_ok:
            if safely_needed:
                print "Fleet %d at %s needs repair but deemed safely needed to remain for defense" % (
                    fleet_id,
                    ppstring(PlanetUtilsAI.sys_name_ids([fleet.systemID])),
                )
            else:
                if needed_here:
                    print "Fleet %d at %s needed present for combat, but is damaged and deemed unsafe to remain." % (
                        fleet_id,
                        ppstring(PlanetUtilsAI.sys_name_ids([fleet.systemID])),
                    )
                    print "\t my_local_rating: %.1f ; threat: %.1f" % (
                        my_local_rating,
                        local_status.get("totalThreat", 0),
                    )
                print "Selecting fleet %d at %s for repair" % (
                    fleet_id,
                    ppstring(PlanetUtilsAI.sys_name_ids([fleet.systemID])),
                )
        fleet_buckets[fleet_ok or safely_needed].append(fleet_id)
    return fleet_buckets
Esempio n. 16
0
    def refresh(self):
        """Turn start AIstate cleanup/refresh."""
        universe = fo.getUniverse()
        # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
        fleetsLostBySystem.clear()
        invasionTargets[:] = []
        exploration_center = PlanetUtilsAI.get_capital_sys_id()
        if exploration_center == -1:  # a bad state probably from an old savegame, or else empire has lost (or almost has)
            exploration_center = self.__origin_home_system_id

        # check if planets in cache is still present. Remove destroyed.
        for system_id, info in sorted(self.systemStatus.items()):
            planet_dict = info.get('planets', {})
            cache_planet_set = set(planet_dict)
            system_planet_set = set(universe.getSystem(system_id).planetIDs)
            diff = cache_planet_set - system_planet_set
            if diff:
                print "Removing destroyed planets from systemStatus for system %s: planets to be removed: %s" % (system_id, sorted(diff))
                for key in diff:
                    del planet_dict[key]

        ExplorationAI.graphFlags.clear()
        if fo.currentTurn() < 50:
            print "-------------------------------------------------"
            print "Border Exploration Update (relative to %s)" % (PlanetUtilsAI.sys_name_ids([exploration_center, -1])[0])
            print "-------------------------------------------------"
        if self.visBorderSystemIDs.keys() == [-1]:
            self.visBorderSystemIDs.clear()
            self.visBorderSystemIDs[exploration_center] = 1
        for sys_id in self.visBorderSystemIDs.keys():  # This dict modified during iteration.
            if fo.currentTurn() < 50:
                print "Considering border system %s" % (PlanetUtilsAI.sys_name_ids([sys_id, -1])[0])
            ExplorationAI.follow_vis_system_connections(sys_id, exploration_center)
        newly_explored = ExplorationAI.update_explored_systems()
        nametags = []
        for sys_id in newly_explored:
            newsys = universe.getSystem(sys_id)
            nametags.append("ID:%4d -- %-20s" % (sys_id, (newsys and newsys.name) or "name unknown"))  # an explored system *should* always be able to be gotten
        if newly_explored:
            print "-------------------------------------------------"
            print "Newly explored systems:\n%s" % "\n".join(nametags)
            print "-------------------------------------------------"
        # cleanup fleet roles
        # self.update_fleet_locs()
        self.__clean_fleet_roles()
        self.__clean_fleet_missions(FleetUtilsAI.get_empire_fleet_ids())
        print "Fleets lost by system: %s" % fleetsLostBySystem
        self.update_system_status()
Esempio n. 17
0
def startNewGame(aggression=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring new game start message."
        return

    turn_timer.start("Server Processing")
    print "New game started, AI Aggression level %d (%s)" % (aggression, UserString(_aggression_names[aggression]))

    # initialize AIstate
    global foAIstate
    print "Initializing foAIstate..."
    foAIstate = AIstate.AIstate(aggression)
    foAIstate.session_start_cleanup()
    print "Initialization of foAIstate complete!"
    print "Trying to rename our homeworld..."
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id is not None and planet_id != -1:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([random.choice(_capitals.get(aggression, []) or [" "]).strip(), planet.name])
        print "    Renaming to %s..." % new_name
        res = fo.issueRenameOrder(planet_id, new_name)
        print "    Result: %d; Planet is now named %s" % (res, planet.name)

    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Esempio n. 18
0
def printResourcesPriority():
    "calculate top resource priority"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    ownedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    print "Resource 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)
    # what is the focus of available resource centers?
    print ""
    print "Planet Resources Foci:"
    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)
Esempio n. 19
0
def system_could_have_unknown_stationary_guard(system_id: SystemId) -> bool:
    """Return True if the system may have spawned stationary guards.

    A stationary guard is defined as immobile monster fleets spawned at game start.
    If this function indicates that there is no such guard, there still may be other threats.
    """
    # We do not play around invisible guards, so if system was visible at some point,
    # there should not be a stationary guard there
    system_was_visible = get_partial_visibility_turn(system_id) > 0
    if system_was_visible:
        return False

    # Universe setup settings may forbid guards
    if fo.getGalaxySetupData(
    ).monsterFrequency == fo.galaxySetupOptionMonsterFreq.none:
        return False

    # Stationary guards require some distance to the home system to be spawned
    home_system = PlanetUtilsAI.get_capital_sys_id()
    jump_distance_to_home_system = fo.getUniverse().jumpDistance(
        system_id, home_system)
    if jump_distance_to_home_system < MINIMUM_GUARD_DISTANCE_TO_HOME_SYSTEM:
        return False

    # No indicator that there isn't a stationary guard
    return True
Esempio n. 20
0
def startNewGame(aggression=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring new game start message."
        return

    turn_timer.start("Server Processing")
    print "New game started, AI Aggression level %d" % aggression

    # initialize AIstate
    global foAIstate
    foAIstate = AIstate.AIstate(aggression=aggression)
    foAIstate.session_start_cleanup()
    print "Initialized foAIstate class"
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id is not None and planet_id != -1:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([random.choice(_capitals.get(aggression, []) or [" "]).strip(), planet.name])
        print "Capitol City Names are: ", _capitals
        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)

    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression, DiplomaticCorp.DiplomaticCorp)()
Esempio n. 21
0
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
Esempio n. 22
0
def startNewGame(aggression_input=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring new game start message."
        return

    turn_timer.start("Server Processing")

    # initialize AIstate
    global foAIstate
    print "Initializing foAIstate..."
    foAIstate = AIstate.AIstate(aggression_input)
    aggression_trait = foAIstate.character.get_trait(Aggression)
    print "New game started, AI Aggression level %d (%s)" % (
        aggression_trait.key, get_trait_name_aggression(foAIstate.character))
    foAIstate.session_start_cleanup()
    print "Initialization of foAIstate complete!"
    print "Trying to rename our homeworld..."
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id is not None and planet_id != INVALID_ID:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([random.choice(possible_capitals(foAIstate.character)).strip(), planet.name])
        print "    Renaming to %s..." % new_name
        res = fo.issueRenameOrder(planet_id, new_name)
        print "    Result: %d; Planet is now named %s" % (res, planet.name)

    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression_trait.key, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Esempio n. 23
0
def startNewGame(aggression_input=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Ignoring new game start message.")
        return

    if empire.eliminated:
        info(
            "This empire has been eliminated. Ignoring new game start message."
        )
        return
    # initialize AIstate
    debug("Initializing AI state...")
    create_new_aistate(aggression_input)
    aistate = get_aistate()
    aggression_trait = aistate.character.get_trait(Aggression)
    debug("New game started, AI Aggression level %d (%s)" %
          (aggression_trait.key, get_trait_name_aggression(aistate.character)))
    aistate.session_start_cleanup()
    debug("Initialization of AI state complete!")
    debug("Trying to rename our homeworld...")
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id is not None and planet_id != INVALID_ID:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([
            random.choice(possible_capitals(aistate.character)).strip(),
            planet.name
        ])
        debug("    Renaming to %s..." % new_name)
        res = fo.issueRenameOrder(planet_id, new_name)
        debug("    Result: %d; Planet is now named %s" % (res, planet.name))
    _pre_game_start(empire.empireID, aistate)
Esempio n. 24
0
    def print_resources_priority():
        """Calculate top resource priority."""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(
            universe.planetIDs)
        debug("Resource Priorities:")
        resource_priorities = {}
        aistate = get_aistate()
        for priority_type in get_priority_resource_types():
            resource_priorities[priority_type] = aistate.get_priority(
                priority_type)

        sorted_priorities = sorted(resource_priorities.items(),
                                   key=itemgetter(1),
                                   reverse=True)
        top_priority = -1
        for evaluation_priority, evaluation_score in sorted_priorities:
            if top_priority < 0:
                top_priority = evaluation_priority
            debug("  %s: %.2f", evaluation_priority, evaluation_score)

        # what is the focus of available resource centers?
        debug("")
        warnings = {}
        foci_table = Table(
            Text("Planet"),
            Text("Size"),
            Text("Type"),
            Text("Focus"),
            Text("Species"),
            Text("Pop"),
            table_name="Planetary Foci Overview Turn %d" % fo.currentTurn(),
        )
        for pid in empire_planet_ids:
            planet = universe.getPlanet(pid)
            population = planet.currentMeterValue(fo.meterType.population)
            max_population = planet.currentMeterValue(
                fo.meterType.targetPopulation)
            if max_population < 1 and population > 0:
                warnings[planet.name] = (population, max_population)
            foci_table.add_row(
                planet,
                planet.size,
                planet.type,
                "_".join(str(planet.focus).split("_")[1:])[:8],
                planet.speciesName,
                "%.1f/%.1f" % (population, max_population),
            )
        foci_table.print_table(info)
        debug(
            "Empire Totals:\nPopulation: %5d \nProduction: %5d\nResearch: %5d\n",
            empire.population(),
            empire.productionPoints,
            empire.resourceProduction(fo.resourceType.research),
        )
        for name, (cp, mp) in warnings.items():
            warning(
                "Population Warning! -- %s has unsustainable current pop %d -- target %d",
                name, cp, mp)
Esempio n. 25
0
def calculateIndustryPriority():
    "calculates the demand for industry"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    # get current industry production & Target
    industryProduction = empire.resourceProduction(fo.resourceType.industry)
    ownedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    planets = map(universe.getPlanet,  ownedPlanetIDs)
    targetPP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetIndustry),  planets) )

    if fo.currentTurn() < 20:
        industryPriority = 20 # mid industry , high research at beginning of game to get easy gro tech
    elif fo.currentTurn() < 30:
        industryPriority = 25 # mid industry , mid research 
    elif fo.currentTurn() < 40:
        industryPriority = 40 # high  industry , mid research 
    elif fo.currentTurn() < 50:
        industryPriority = 50 # high  industry , mid research 
    else:
        industryPriority = 60 # high  industry , low-mid research 


    # increase demand for industry industry production is low
    #industryPriority = 380 / (industryProduction + 0.001)

    print ""
    print "Industry Production (current/target) : ( %.1f / %.1f )  at turn %s"%(industryProduction,  targetPP,  fo.currentTurn())
    print "Priority for Industry: " + str(industryPriority)

    return industryPriority
Esempio n. 26
0
def calculateResearchPriority():
    "calculates the AI empire's demand for research"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    gotAlgo = empire.getTechStatus("LRN_ALGO_ELEGANCE") == fo.techStatus.complete

    
    totalPP = empire.productionPoints
    totalRP = empire.resourceProduction(fo.resourceType.research)
    # get current industry production & Target
    ownedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    planets = map(universe.getPlanet,  ownedPlanetIDs)
    targetRP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetResearch),  planets) )

    if  (fo.currentTurn() < 20) or not gotAlgo:
        researchPriority = 60 # mid industry , high research at beginning of game to get easy gro tech and to get research booster Algotrithmic Elegance
    elif fo.currentTurn() < 30:
        researchPriority = 30 # mid industry , mid research 
    elif fo.currentTurn() < 40:
        researchPriority = 20 # high  industry , low research 
    else:
        researchPriority = 15 # high  industry , low research 


    print  ""
    print  "Research Production (current/target) : ( %.1f / %.1f )"%(totalRP,  targetRP)
    print  "Priority for Research: " + str(researchPriority)

    return researchPriority
Esempio n. 27
0
 def __border_exploration_update(self):
     universe = fo.getUniverse()
     exploration_center = PlanetUtilsAI.get_capital_sys_id()
     # a bad state probably from an old savegame, or else empire has lost (or almost has)
     if exploration_center == INVALID_ID:
         exploration_center = self.__origin_home_system_id
     ExplorationAI.graph_flags.clear()
     if fo.currentTurn() < 50:
         debug("-------------------------------------------------")
         debug("Border Exploration Update (relative to %s)" % universe.getSystem(exploration_center))
         debug("-------------------------------------------------")
     if self.visBorderSystemIDs == {INVALID_ID}:
         self.visBorderSystemIDs.clear()
         self.visBorderSystemIDs.add(exploration_center)
     for sys_id in list(self.visBorderSystemIDs):  # This set is modified during iteration.
         if fo.currentTurn() < 50:
             debug("Considering border system %s" % universe.getSystem(sys_id))
         ExplorationAI.follow_vis_system_connections(sys_id, exploration_center)
     newly_explored = ExplorationAI.update_explored_systems()
     nametags = []
     for sys_id in newly_explored:
         newsys = universe.getSystem(sys_id)
         # an explored system *should* always be able to be gotten
         nametags.append("ID:%4d -- %-20s" % (sys_id, (newsys and newsys.name) or "name unknown"))
     if newly_explored:
         debug("-------------------------------------------------")
         debug("Newly explored systems:\n%s" % "\n".join(nametags))
         debug("-------------------------------------------------")
Esempio n. 28
0
def avail_mil_needing_repair(mil_fleet_ids, split_ships=False, on_mission=False):
    """returns tuple of lists-- ( ids_needing_repair, ids_not )"""
    fleet_buckets = [[], []]
    universe = fo.getUniverse()
    cutoff = [0.70, 0.25][ on_mission ]
    for fleet_id in mil_fleet_ids:
        fleet = universe.getFleet(fleet_id)
        ship_buckets = [ [], [] ]
        ships_cur_health = [ 0, 0 ]
        ships_max_health = [ 0, 0 ]
        for ship_id in fleet.shipIDs:
            this_ship = universe.getShip(ship_id)
            cur_struc = this_ship.currentMeterValue(fo.meterType.structure)
            max_struc = this_ship.currentMeterValue(fo.meterType.maxStructure)
            ship_ok = cur_struc >= cutoff * max_struc
            ship_buckets[ship_ok].append( ship_id )
            ships_cur_health[ship_ok] += cur_struc
            ships_max_health[ship_ok] += max_struc
        #TODO: the following is a temp all-or-nothing test
        fleet_ok = ( sum(ships_cur_health) >= cutoff * sum(ships_max_health) )
        if not fleet_ok:
            pass
            print "Selecting fleet %d at %s for repair"%(fleet_id, PlanetUtilsAI.sys_name_ids( [fleet.systemID] ))
        fleet_buckets[fleet_ok].append(fleet_id)
    return fleet_buckets
Esempio n. 29
0
def calculateMilitaryPriority():
    "calculates the demand for military ships by military targeted systems"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    capitalID = PlanetUtilsAI.getCapital()
    if capitalID:
        homeworld = universe.getPlanet(capitalID)
    else:
        return 0# no capitol (not even a capitol-in-the-making), means can't produce any ships
    allottedInvasionTargets = 1+ int(fo.currentTurn()/25)
    targetPlanetIDs =  [pid for pid, pscore, trp in AIstate.invasionTargets[:allottedInvasionTargets] ] + [pid for pid,  pscore in foAI.foAIstate.colonisablePlanetIDs[:allottedColonyTargets]  ] + [pid for pid,  pscore in foAI.foAIstate.colonisableOutpostIDs[:allottedColonyTargets]  ]
    
    mySystems = set( AIstate.popCtrSystemIDs ).union( AIstate.outpostSystemIDs   )
    targetSystems = set( PlanetUtilsAI.getSystems(targetPlanetIDs)  )
    
    curShipRating = 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)
Esempio n. 30
0
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)
Esempio n. 31
0
def get_repair_fleet_order(fleet_target, current_sys_id):
    """ Returns repair AIFleetOrder to [nearest safe] drydock."""
    # find nearest supplied system
    drydock_sys_id = get_nearest_drydock_system_id(current_sys_id)
    drydock_system_target = AITarget.AITarget(AITargetType.TARGET_SYSTEM, drydock_sys_id)
    print "ordering fleet %d to %s for repair" % (fleet_target.target_id, PlanetUtilsAI.sys_name_ids([drydock_sys_id]))
    # create resupply AIFleetOrder
    return AIFleetOrder.AIFleetOrder(AIFleetOrderType.ORDER_REPAIR, fleet_target, drydock_system_target)
def inspect_ai_interface():
    capital_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    fleets_int_vector = universe.fleetIDs
    fleet = universe.getFleet(list(fleets_int_vector)[0])
    ship = universe.getShip(list(universe.shipIDs)[0])
    design = fo.getShipDesign(ship.designID)
    empire = fo.getEmpire()

    tech = fo.getTech('SHP_WEAPON_2_1')
    tech_spec = list(tech.unlockedItems)[0]

    part_id = list(empire.availableShipParts)[0]
    part_type = fo.getPartType(part_id)

    prod_queue = empire.productionQueue
    fo.issueEnqueueShipProductionOrder(
        list(empire.availableShipDesigns)[0], capital_id)

    research_queue = empire.researchQueue

    fo.issueEnqueueTechOrder('SHP_WEAPON_1_2', -1)

    planet = universe.getPlanet(capital_id)

    building = list(planet.buildingIDs)[0]

    inspect(
        fo,
        universe,
        fleet,
        planet,
        universe.getSystem(planet.systemID),
        ship,
        empire,
        design,
        tech,
        tech_spec,
        fo.getFieldType('FLD_ION_STORM'),
        fo.getBuildingType('BLD_SHIPYARD_BASE'),
        fo.getGalaxySetupData(),
        fo.getHullType('SH_XENTRONIUM'),
        fo.getPartType('SR_WEAPON_1_1'),
        fo.getSpecial('MODERATE_TECH_NATIVES_SPECIAL'),
        fo.getSpecies('SP_ABADDONI'),
        fo.getTech('SHP_WEAPON_4_1'),
        fo.diplomaticMessage(1, 2, fo.diplomaticMessageType.acceptProposal),
        fleets_int_vector,
        part_type,
        prod_queue,
        prod_queue.allocatedPP,
        prod_queue[0],
        research_queue,
        research_queue[0],
        empire.getSitRep(0),
        universe.getBuilding(building),
    )
    exit(1)  # exit game to main menu no need to play anymore.
def inspect_FreeOrionAIInterface():
    capital_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    fleets_int_vector = universe.fleetIDs
    fleet = universe.getFleet(list(fleets_int_vector)[0])
    ship = universe.getShip(list(universe.shipIDs)[0])
    design = fo.getShipDesign(ship.designID)
    empire = fo.getEmpire()

    tech = fo.getTech('SHP_WEAPON_2_1')
    tech_spec = list(tech.unlockedItems)[0]

    part_id = list(empire.availableShipParts)[0]
    part_type = fo.getPartType(part_id)

    prod_queue = empire.productionQueue
    fo.issueEnqueueShipProductionOrder(list(empire.availableShipDesigns)[0], capital_id)

    research_queue = empire.researchQueue

    fo.issueEnqueueTechOrder('SHP_WEAPON_1_2', -1)

    planet = universe.getPlanet(capital_id)

    building = list(planet.buildingIDs)[0]

    inspect(
        fo,
        universe,
        fleet,
        planet,
        universe.getSystem(planet.systemID),
        ship,
        empire,
        design,
        tech,
        tech_spec,
        fo.getFieldType('FLD_ION_STORM'),
        fo.getBuildingType('BLD_SHIPYARD_BASE'),
        fo.getGalaxySetupData(),
        fo.getHullType('SH_XENTRONIUM'),
        fo.getPartType('SR_WEAPON_1_1'),
        fo.getSpecial('MODERATE_TECH_NATIVES_SPECIAL'),
        fo.getSpecies('SP_ABADDONI'),
        fo.getTech('SHP_WEAPON_4_1'),
        fo.diplomaticMessage(1, 2, fo.diplomaticMessageType.acceptProposal),
        fleets_int_vector,
        part_type,
        prod_queue,
        prod_queue.allocatedPP,
        prod_queue[0],
        research_queue,
        research_queue[0],
        empire.getSitRep(0),
        universe.getBuilding(building),
    )
    exit(1)  # exit game to main menu no need to play anymore.
Esempio n. 34
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
Esempio n. 35
0
def get_safe_path_leg_to_dest(fleet_id, start_id, dest_id):
    start_targ = TargetSystem(start_id)
    dest_targ = TargetSystem(dest_id)
    # TODO actually get a safe path
    this_path = can_travel_to_system(fleet_id, start_targ, dest_targ, ensure_return=False)
    path_ids = [targ.id for targ in this_path if targ.id != start_id] + [start_id]
    universe = fo.getUniverse()
    debug("Fleet %d requested safe path leg from %s to %s, found path %s" % (
        fleet_id, universe.getSystem(start_id), universe.getSystem(dest_id), PlanetUtilsAI.sys_name_ids(path_ids)))
    return path_ids[0]
Esempio n. 36
0
def getRepairAIFleetOrder(fleetAITarget, current_sys_id):
    "returns repair AIFleetOrder to [nearest safe] drydock"
    # find nearest supplied system
    empireID = fo.empireID()
    drydock_sys_id = getNearestDrydockSystemID(current_sys_id)
    drydockSystemAITarget = AITarget.AITarget(AITargetType.TARGET_SYSTEM, drydock_sys_id)
    print "ordering fleet %d to %s for repair"%(fleetAITarget.target_id,  PlanetUtilsAI.sysNameIDs([drydock_sys_id]))
    # create resupply AIFleetOrder
    aiFleetOrder = AIFleetOrder.AIFleetOrder(AIFleetOrderType.ORDER_REPAIR, fleetAITarget, drydockSystemAITarget)
    return aiFleetOrder
Esempio n. 37
0
def calculateResearchPriority():
    "calculates the AI empire's demand for research"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    
    industryPriority = foAI.foAIstate.getPriority(EnumsAI.AIPriorityType.PRIORITY_RESOURCE_PRODUCTION)
    
    gotAlgo = empire.getTechStatus("LRN_ALGO_ELEGANCE") == fo.techStatus.complete
    researchQueueList = ResearchAI.getResearchQueueTechs()
    orbGenTech = "PRO_ORBITAL_GEN"
        
    totalPP = empire.productionPoints
    totalRP = empire.resourceProduction(fo.resourceType.research)
    industrySurge=   (foAI.foAIstate.aggression > fo.aggression.cautious) and  ( totalPP <(30*(foAI.foAIstate.aggression))  )  and (orbGenTech  in researchQueueList[:3]  or  empire.getTechStatus(orbGenTech) == fo.techStatus.complete)
    # get current industry production & Target
    ownedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    planets = map(universe.getPlanet,  ownedPlanetIDs)
    targetRP = sum( map( lambda x: x.currentMeterValue(fo.meterType.targetResearch),  planets) )

    styleIndex = empireID%2
    cutoffSets =  [ [25, 45, 70  ],  [35,  50,  70  ]   ]
    cutoffs = cutoffSets[styleIndex  ] 
    settings = [ [2, .6, .4, .35  ],  [1.4,  .7,  .4, .35   ]   ][styleIndex  ] 
    
    if industrySurge and True:
        researchPriority =  0.2 * industryPriority
    else:
        if  (fo.currentTurn() < cutoffs[0]) or not gotAlgo:
            researchPriority = settings[0] * industryPriority # high research at beginning of game to get easy gro tech and to get research booster Algotrithmic Elegance
        elif fo.currentTurn() < cutoffs[1]:
            researchPriority = settings[1] * industryPriority# med-high research 
        elif fo.currentTurn() < cutoffs[2]:
            researchPriority = settings[2] * industryPriority # med-high  industry 
        else:
            researchQueue = list(empire.researchQueue)
            researchPriority = settings[3] * industryPriority # high  industry , low research 
            if len(researchQueue) == 0 :
                researchPriority = 0 # done with research
            elif len(researchQueue) <5 and researchQueue[-1].allocation > 0 :
                researchPriority =  len(researchQueue) # barely not done with research 
            elif len(researchQueue) <10 and researchQueue[-1].allocation > 0 :
                researchPriority = 4+ len(researchQueue) # almost done with research 
            elif len(researchQueue) <20 and researchQueue[int(len(researchQueue)/2)].allocation > 0 :
                researchPriority = 0.5 * researchPriority # closing in on end of research 
            elif len(researchQueue) <20:
                researchPriority = 0.7*researchPriority # high  industry , low research 

    print  ""
    print  "Research Production (current/target) : ( %.1f / %.1f )"%(totalRP,  targetRP)
    print  "Priority for Research: " + str(researchPriority)

    return researchPriority
Esempio n. 38
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
Esempio n. 39
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    #explorable_system_ids = foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    explorable_system_ids = list(borderUnexploredSystemIDs)
    if not explorable_system_ids or (capital_sys_id == -1):
        return
    exp_systems_by_dist = sorted(map(lambda x: (universe.linearDistance(capital_sys_id, x), x), explorable_system_ids))
    print "Exploration system considering following system-distance pairs:\n %s" % ("[ " + ", ".join(["%3d : %5.1f" % (sys, dist) for dist, sys in exp_systems_by_dist]) + " ]")
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist]

    already_covered, available_scouts = get_current_exploration_info()

    print "explorable sys IDs: %s" % explore_list
    print "already targeted: %s" % already_covered
    if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
        foAI.foAIstate.needsEmergencyExploration = []
    needs_coverage = foAI.foAIstate.needsEmergencyExploration + [sys_id for sys_id in explore_list if sys_id not in already_covered]  # emergency coverage cane be due to invasion detection trouble, etc.
    print "needs coverage: %s" % needs_coverage

    print "available scouts & AIstate locs: %s" % (map(lambda x: (x, foAI.foAIstate.fleetStatus.get(x, {}).get('sysID', -1)), available_scouts))
    print "available scouts & universe locs: %s" % (map(lambda x: (x, universe.getFleet(x).systemID), available_scouts))
    if not needs_coverage or not available_scouts:
        return

    available_scouts = set(available_scouts)
    sent_list = []
    while (len(available_scouts) > 0) and (len(needs_coverage) > 0):
        this_sys_id = needs_coverage.pop(0)
        if (foAI.foAIstate.systemStatus.setdefault(this_sys_id, {}).setdefault('monsterThreat', 0) > 2000 * foAI.foAIstate.aggression) or (fo.currentTurn() < 20 and foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'] > 200):
            print "Skipping exploration of system %d due to Big Monster, threat %d" % (this_sys_id, foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'])
            continue
        found_fleets = []
        this_fleet_list = FleetUtilsAI.get_fleets_for_mission(nships=1, target_stats={}, min_stats={}, cur_stats={}, species="", systems_to_check=[this_sys_id], systems_checked=[],
                                                     fleet_pool_set=available_scouts, fleet_list=found_fleets, verbose=False)
        if not this_fleet_list:
            print "seem to have run out of scouts while trying to cover sys_id %d" % this_sys_id
            break  # must have ran out of scouts
        fleet_id = this_fleet_list[0]
        fleet_mission = foAI.foAIstate.get_fleet_mission(fleet_id)
        target = AITarget.AITarget(TargetType.TARGET_SYSTEM, this_sys_id)
        if len(MoveUtilsAI.can_travel_to_system_and_return_to_resupply(fleet_id, fleet_mission.get_location_target(), target)) > 0:
            fleet_mission.add_target(AIFleetMissionType.FLEET_MISSION_EXPLORATION, target)
            sent_list.append(this_sys_id)
        else:  # system too far out, skip it, but can add scout back to available pool
            print "sys_id %d too far out for fleet ( ID %d ) to reach" % (this_sys_id, fleet_id)
            available_scouts.update(this_fleet_list)
    print "sent scouting fleets to sysIDs : %s" % sent_list
    return
    # pylint: disable=pointless-string-statement
    """
Esempio n. 40
0
    def print_resources_priority():
        """Calculate top resource priority."""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(
            universe.planetIDs)
        print "Resource Priorities:"
        resource_priorities = {}
        for priority_type in get_priority_resource_types():
            resource_priorities[priority_type] = foAI.foAIstate.get_priority(
                priority_type)

        sorted_priorities = resource_priorities.items()
        sorted_priorities.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)
        top_priority = -1
        for evaluation_priority, evaluation_score in sorted_priorities:
            if top_priority < 0:
                top_priority = evaluation_priority
            print "  %s: %.2f" % (evaluation_priority, evaluation_score)

        # what is the focus of available resource centers?
        print
        warnings = {}
        foci_table = Table([
            Text('Planet'),
            Text('Size'),
            Text('Type'),
            Text('Focus'),
            Text('Species'),
            Text('Pop')
        ],
                           table_name="Planetary Foci Overview Turn %d" %
                           fo.currentTurn())
        for pid in empire_planet_ids:
            planet = universe.getPlanet(pid)
            population = planet.currentMeterValue(fo.meterType.population)
            max_population = planet.currentMeterValue(
                fo.meterType.targetPopulation)
            if max_population < 1 and population > 0:
                warnings[planet.name] = (population, max_population)
            foci_table.add_row([
                planet, planet.size, planet.type,
                "_".join(str(planet.focus).split("_")[1:])[:8],
                planet.speciesName,
                "%.1f/%.1f" % (population, max_population)
            ])
        foci_table.print_table()
        print "Empire Totals:\nPopulation: %5d \nProduction: %5d\nResearch: %5d\n" % (
            empire.population(), empire.productionPoints,
            empire.resourceProduction(fo.resourceType.research))
        for name, (cp, mp) in warnings.iteritems():
            print "Population Warning! -- %s has unsustainable current pop %d -- target %d" % (
                name, cp, mp)
Esempio n. 41
0
def calculateMilitaryPriority():
    "calculates the demand for military ships by military targeted systems"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    capitalID = PlanetUtilsAI.getCapital()
    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)
Esempio n. 42
0
    def issue_order(self):
        if not super(OrderRepair, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            fo.issueAggressionOrder(fleet_id, False)
            start_id = FleetUtilsAI.get_fleet_system(fleet)
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
                fleet_id, self.ORDER_NAME, PlanetUtilsAI.sys_name_ids([dest_id]),
                PlanetUtilsAI.sys_name_ids([system_id]))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    foAI.foAIstate.needsEmergencyExploration.remove(system_id)
            self.order_issued = True
Esempio n. 43
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    #explorable_system_ids = foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    explorable_system_ids = list(borderUnexploredSystemIDs)
    if not explorable_system_ids or (capital_sys_id == -1):
        return
    exp_systems_by_dist = sorted(map(lambda x: (universe.linearDistance(capital_sys_id, x), x), explorable_system_ids))
    print "Exploration system considering following system-distance pairs:\n %s"%("[ "+ ", ".join(["%3d : %5.1f"%(sys, dist) for dist, sys in exp_systems_by_dist]) +" ]")
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist ]

    already_covered, available_scouts = get_current_exploration_info()

    print "explorable sys IDs: %s"%explore_list
    print "already targeted: %s"%already_covered
    if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
        foAI.foAIstate.needsEmergencyExploration = []
    needs_coverage = foAI.foAIstate.needsEmergencyExploration + [sys_id for sys_id in explore_list if sys_id not in already_covered ] # emergency coverage cane be due to invasion detection trouble, etc.
    print "needs coverage: %s"%needs_coverage

    print "available scouts & AIstate locs: %s" % (map(lambda x: (x, foAI.foAIstate.fleetStatus.get(x, {}).get('sysID', -1)), available_scouts) )
    print "available scouts & universe locs: %s" % (map(lambda x: (x, universe.getFleet(x).systemID), available_scouts))
    if not needs_coverage or not available_scouts:
        return

    available_scouts = set(available_scouts)
    sent_list = []
    while (len(available_scouts) > 0 ) and ( len(needs_coverage) > 0):
        this_sys_id = needs_coverage.pop(0)
        if (foAI.foAIstate.systemStatus.setdefault(this_sys_id, {}).setdefault('monsterThreat', 0) > 2000* foAI.foAIstate.aggression ) or (fo.currentTurn() <20 and foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'] > 200):
            print "Skipping exploration of system %d due to Big Monster, threat %d"%(this_sys_id, foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'])
            continue
        found_fleets=[]
        this_fleet_list = FleetUtilsAI.get_fleets_for_mission(nships=1, target_stats={}, min_stats={}, cur_stats={}, species="", systems_to_check=[this_sys_id], systems_checked=[],
                                                     fleet_pool_set= available_scouts, fleet_list=found_fleets, verbose=False)
        if not this_fleet_list:
            print "seem to have run out of scouts while trying to cover sys_id %d"%this_sys_id
            break #must have ran out of scouts
        fleet_id = this_fleet_list[0]
        fleet_mission = foAI.foAIstate.get_fleet_mission( fleet_id )
        target = AITarget.AITarget(AITargetType.TARGET_SYSTEM, this_sys_id )
        if len(MoveUtilsAI.can_travel_to_system_and_return_to_resupply(fleet_id, fleet_mission.get_location_target(), target)) > 0:
            fleet_mission.add_target(AIFleetMissionType.FLEET_MISSION_EXPLORATION, target)
            sent_list.append(this_sys_id)
        else: #system too far out, skip it, but can add scout back to available pool
            print "sys_id %d too far out for fleet ( ID %d ) to readch"%(this_sys_id, fleet_id)
            available_scouts.update(this_fleet_list)
    print "sent scouting fleets to sysIDs : %s"%sent_list
    return
    # pylint: disable=pointless-string-statement
    """
Esempio n. 44
0
def _print_empire_capital():
    planet_id = PlanetUtilsAI.get_capital()
    if planet_id is not None and planet_id != INVALID_ID:
        planet = fo.getUniverse().getPlanet(planet_id)
        stats.capital(planet_id, planet.name, planet.speciesName)
    else:
        stats.capital(None, None, None)
    debug(
        "***************************************************************************"
    )
    debug(
        "***************************************************************************"
    )
Esempio n. 45
0
def print_resources_priority():
    """calculate top resource priority"""
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empirePlanetIDs = PlanetUtilsAI.get_owned_planets_by_empire(
        universe.planetIDs)
    print "Resource Management:"
    print
    print "Resource Priorities:"
    resourcePriorities = {}
    for priorityType in get_priority_resource_types():
        resourcePriorities[priorityType] = foAI.foAIstate.get_priority(
            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 "    ResourcePriority |Score: %s | %s " % (
            AIPriorityTypeNames.name(evaluationPair[0]), evaluationPair[1])

    # what is the focus of available resource centers?
    print
    warnings = {}
    print "Planet Resources Foci:"
    for planetID in empirePlanetIDs:
        planet = universe.getPlanet(planetID)
        planetPopulation = planet.currentMeterValue(fo.meterType.population)
        maxPop = planet.currentMeterValue(fo.meterType.targetPopulation)
        if maxPop < 1 and planetPopulation > 0:
            warnings[planet.name] = (planetPopulation, maxPop)
        statusStr = "  ID: " + str(planetID) + " Name: % 18s -- % 6s % 8s " % (
            str(planet.name), str(planet.size), str(planet.type))
        statusStr += " Focus: % 8s" % ("_".join(
            str(planet.focus).split("_")[1:])[:8]) + " Species: " + str(
                planet.speciesName) + " Pop: %2d/%2d" % (planetPopulation,
                                                         maxPop)
        print statusStr
    print "\n\nEmpire Totals:\nPopulation: %5d \nProduction: %5d\nResearch: %5d\n" % (
        empire.population(), empire.productionPoints,
        empire.resourceProduction(fo.resourceType.research))
    if warnings != {}:
        for pname in warnings:
            mp, cp = warnings[pname]
            print "Population Warning! -- %s has unsustainable current pop %d -- target %d" % (
                pname, cp, mp)
        print
    warnings.clear()
Esempio n. 46
0
    def print_resources_priority():
        """Calculate top resource priority."""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(
            universe.planetIDs)
        print "Resource Management:"
        print
        print "Resource Priorities:"
        resource_priorities = {}
        for priority_type in get_priority_resource_types():
            resource_priorities[priority_type] = foAI.foAIstate.get_priority(
                priority_type)

        sorted_priorities = resource_priorities.items()
        sorted_priorities.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)
        top_priority = -1
        for evaluation_priority, evaluation_score in sorted_priorities:
            if top_priority < 0:
                top_priority = evaluation_priority
            print "    ResourcePriority |Score: %s | %s " % (
                evaluation_priority, evaluation_score)

        # what is the focus of available resource centers?
        print
        warnings = {}
        # TODO combine this with previous table to reduce report duplication?
        print "Planet Resources Foci:"
        for pid in empire_planet_ids:
            planet = universe.getPlanet(pid)
            population = planet.currentMeterValue(fo.meterType.population)
            max_population = planet.currentMeterValue(
                fo.meterType.targetPopulation)
            if max_population < 1 and population > 0:
                warnings[planet.name] = (population, max_population)
            print "  ID: %d Name: % 18s -- % 6s % 8s  Focus: % 8s Species: %s Pop: %2d/%2d" % (
                pid, planet.name, planet.size, planet.type, "_".join(
                    str(planet.focus).split("_")[1:])[:8], planet.speciesName,
                population, max_population)
        print "\n\nEmpire Totals:\nPopulation: %5d \nProduction: %5d\nResearch: %5d\n" % (
            empire.population(), empire.productionPoints,
            empire.resourceProduction(fo.resourceType.research))
        if warnings != {}:
            for name in warnings:
                mp, cp = warnings[name]
                print "Population Warning! -- %s has unsustainable current pop %d -- target %d" % (
                    name, cp, mp)
            print
        warnings.clear()
Esempio n. 47
0
def get_safe_path_leg_to_dest(fleet_id, start_id, dest_id):
    start_targ = TargetSystem(start_id)
    dest_targ = TargetSystem(dest_id)
    # TODO actually get a safe path
    this_path = can_travel_to_system(fleet_id,
                                     start_targ,
                                     dest_targ,
                                     ensure_return=False)
    path_ids = [targ.id
                for targ in this_path if targ.id != start_id] + [start_id]
    universe = fo.getUniverse()
    debug("Fleet %d requested safe path leg from %s to %s, found path %s" %
          (fleet_id, universe.getSystem(start_id), universe.getSystem(dest_id),
           PlanetUtilsAI.sys_name_ids(path_ids)))
    return path_ids[0]
Esempio n. 48
0
    def __init__(self):
        universe = fo.getUniverse()

        resource_timer.start("getPlanets")
        planet_ids = list(PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs))

        resource_timer.start("Targets")
        self.all_planet_info = {pid: PlanetFocusInfo(universe.getPlanet(pid)) for pid in planet_ids}

        self.raw_planet_info = dict(self.all_planet_info)
        self.baked_planet_info = {}

        for pid, pinfo in self.raw_planet_info.items():
            if not pinfo.planet.availableFoci:
                self.baked_planet_info[pid] = self.raw_planet_info.pop(pid)
Esempio n. 49
0
def startNewGame(aggression_input=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire is None:
        print "This client has no empire. Ignoring new game start message."
        return

    if empire.eliminated:
        info(
            "This empire has been eliminated. Ignoring new game start message."
        )
        return

    turn_timer.start("Server Processing")

    # initialize AIstate
    global foAIstate
    debug("Initializing foAIstate...")
    foAIstate = AIstate.AIstate(aggression_input)
    aggression_trait = foAIstate.character.get_trait(Aggression)
    debug(
        "New game started, AI Aggression level %d (%s)" %
        (aggression_trait.key, get_trait_name_aggression(foAIstate.character)))
    foAIstate.session_start_cleanup()
    debug("Initialization of foAIstate complete!")
    debug("Trying to rename our homeworld...")
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id is not None and planet_id != INVALID_ID:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([
            random.choice(possible_capitals(foAIstate.character)).strip(),
            planet.name
        ])
        debug("    Renaming to %s..." % new_name)
        res = fo.issueRenameOrder(planet_id, new_name)
        debug("    Result: %d; Planet is now named %s" % (res, planet.name))

    diplomatic_corp_configs = {
        fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
        fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp
    }
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(
        aggression_trait.key, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Esempio n. 50
0
def _calculate_industry_priority():  # currently only used to print status
    """calculates the demand for industry"""
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    # get current industry production & Target
    industry_production = empire.resourceProduction(fo.resourceType.industry)
    owned_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)
    planets = map(universe.getPlanet, owned_planet_ids)
    target_pp = sum(map(lambda x: x.currentMeterValue(fo.meterType.targetIndustry), planets))

    # currently, previously set to 50 in calculatePriorities(), this is just for reporting
    industry_priority = foAI.foAIstate.get_priority(PriorityType.RESOURCE_PRODUCTION)

    print
    print "Industry Production (current/target) : ( %.1f / %.1f ) at turn %s" % (industry_production, target_pp, fo.currentTurn())
    print "Priority for Industry: %s" % industry_priority
    return industry_priority
Esempio n. 51
0
def _get_path_from_capital(
        planet: "fo.planet") -> Tuple[Sequence[SystemId], int]:
    """
    Return chain of system from the planet to capital and length.

    If there is no path, return empty sequence and default distance.
    """
    universe = fo.getUniverse()
    capital_id = PlanetUtilsAI.get_capital()
    if capital_id != INVALID_ID:
        homeworld = universe.getPlanet(capital_id)
        if homeworld and homeworld.systemID != INVALID_ID and planet.systemID != INVALID_ID:
            least_jumps_path = list(
                universe.leastJumpsPath(homeworld.systemID, planet.systemID,
                                        fo.empireID()))
            max_jumps = len(least_jumps_path)
            return least_jumps_path, max_jumps
    else:
        return [], 8
Esempio n. 52
0
def get_repair_fleet_order(fleet_target, current_sys_id):
    """
    Return fleet_orders.OrderRepair for fleet to proceed system with drydock.

    :param fleet_target: fleet that need to be repaired
    :type fleet_target: universe_object.Fleet
    # TODO check if we can remove this id, because fleet already have it.
    :param current_sys_id: current system id
    :type current_sys_id: int
    :return: order to repair
    :rtype fleet_orders.OrderRepair
    """
    # TODO Cover new mechanics where happiness increases repair rate - don't always use nearest system!
    # find nearest supplied system
    drydock_sys_id = get_best_drydock_system_id(current_sys_id, fleet_target.id)
    if drydock_sys_id is None:
        return None
    print "ordering fleet %d to %s for repair" % (fleet_target.id, ppstring(PlanetUtilsAI.sys_name_ids([drydock_sys_id])))
    # create resupply AIFleetOrder
    return fleet_orders.OrderRepair(fleet_target, universe_object.System(drydock_sys_id))
Esempio n. 53
0
def _calculate_industry_priority():  # currently only used to print status
    """calculates the demand for industry"""
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    # get current industry production & Target
    industry_production = empire.resourceProduction(fo.resourceType.industry)
    owned_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire()
    planets = (universe.getPlanet(x) for x in owned_planet_ids)
    target_pp = sum(
        x.currentMeterValue(fo.meterType.targetIndustry) for x in planets)

    # currently, previously set to 50 in calculatePriorities(), this is just for reporting
    industry_priority = get_aistate().get_priority(
        PriorityType.RESOURCE_PRODUCTION)

    debug("")
    debug("Industry Production (current/target) : ( %.1f / %.1f ) at turn %s" %
          (industry_production, target_pp, fo.currentTurn()))
    debug("Priority for Industry: %s" % industry_priority)
    return industry_priority
Esempio n. 54
0
def startNewGame(aggression=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    turn_timer.start("Server Processing")
    print "New game started, AI Aggression level %d" % aggression

    # initialize AIstate
    global foAIstate
    foAIstate = AIstate.AIstate(aggression=aggression)
    foAIstate.session_start_cleanup()
    print "Initialized foAIstate class"
    planet_id = PlanetUtilsAI.get_capital()
    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)
Esempio n. 55
0
    def __init__(self):
        universe = fo.getUniverse()

        resource_timer.start("getPlanets")
        planet_ids = list(PlanetUtilsAI.get_owned_planets_by_empire())

        resource_timer.start("Targets")
        self.all_planet_info = {
            pid: PlanetFocusInfo(universe.getPlanet(pid))
            for pid in planet_ids
        }

        self.raw_planet_info = dict(self.all_planet_info)
        self.baked_planet_info = {}
        for pid, pinfo in list(self.raw_planet_info.items()):
            if not pinfo.planet.availableFoci:
                self.baked_planet_info[pid] = self.raw_planet_info.pop(pid)
        aistate = get_aistate()
        self.priority = (
            aistate.get_priority(PriorityType.RESOURCE_PRODUCTION),
            aistate.get_priority(PriorityType.RESOURCE_RESEARCH),
            aistate.get_priority(PriorityType.RESOURCE_INFLUENCE),
        )
Esempio n. 56
0
    def _rate_artisan_planet(self, pid: PlanetId,
                             species_name: SpeciesName) -> float:
        focus_bonus = fo.getNamedValue("ARTISANS_INFLUENCE_FLAT_FOCUS")
        focus_minimum = fo.getNamedValue("ARTISANS_MIN_STABILITY_FOCUS")
        species_focus_bonus = focus_bonus * get_species_tag_value(
            species_name, Tags.INFLUENCE)
        planet = self._universe.getPlanet(pid)
        stability = planet.currentMeterValue(fo.meterType.targetHappiness)
        # First check whether the planet would currently get the focus bonus.
        if planet.focus == FocusType.FOCUS_INFLUENCE:
            return 3 * species_focus_bonus if stability >= focus_minimum else 0.0

        # Planet does not have influence focus...
        # Check for the non-focus bonus. Since we would get this "for free", rate it higher
        non_focus_bonus = fo.getNamedValue("ARTISANS_INFLUENCE_FLAT_NO_FOCUS")
        non_focus_minimum = fo.getNamedValue("ARTISANS_MIN_STABILITY_NO_FOCUS")
        rating = 0.0
        if stability >= non_focus_minimum:
            rating += 4 * non_focus_bonus
        # Check whether this planet would get the focus bonus, if we'd switch it to influence.
        if PlanetUtilsAI.stability_with_focus(
                planet, FocusType.FOCUS_INFLUENCE) >= focus_minimum:
            rating += species_focus_bonus
        return rating
Esempio n. 57
0
def get_invasion_fleets():
    invasion_timer.start("gathering initial info")
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empire_id = fo.empireID()

    home_system_id = PlanetUtilsAI.get_capital_sys_id()
    aistate = get_aistate()
    visible_system_ids = list(aistate.visInteriorSystemIDs) + list(
        aistate.visBorderSystemIDs)

    if home_system_id != INVALID_ID:
        accessible_system_ids = [
            sys_id for sys_id in visible_system_ids
            if systems_connected(sys_id, home_system_id)
        ]
    else:
        debug(
            "Empire has no identifiable homeworld; will treat all visible planets as accessible."
        )
        # TODO: check if any troop ships owned, use their system as home system
        accessible_system_ids = visible_system_ids

    acessible_planet_ids = PlanetUtilsAI.get_planets_in__systems_ids(
        accessible_system_ids)
    all_owned_planet_ids = PlanetUtilsAI.get_all_owned_planet_ids(
        acessible_planet_ids)  # includes unpopulated outposts
    all_populated_planets = PlanetUtilsAI.get_populated_planet_ids(
        acessible_planet_ids)  # includes unowned natives
    empire_owned_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(
        universe.planetIDs)
    invadable_planet_ids = set(all_owned_planet_ids).union(
        all_populated_planets) - set(empire_owned_planet_ids)

    invasion_targeted_planet_ids = get_invasion_targeted_planet_ids(
        universe.planetIDs, MissionType.INVASION)
    invasion_targeted_planet_ids.extend(
        get_invasion_targeted_planet_ids(universe.planetIDs,
                                         MissionType.ORBITAL_INVASION))
    all_invasion_targeted_system_ids = set(
        PlanetUtilsAI.get_systems(invasion_targeted_planet_ids))

    invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(
        MissionType.INVASION)
    num_invasion_fleets = len(
        FleetUtilsAI.extract_fleet_ids_without_mission_types(
            invasion_fleet_ids))

    debug("Current Invasion Targeted SystemIDs: %s" %
          PlanetUtilsAI.sys_name_ids(AIstate.invasionTargetedSystemIDs))
    debug("Current Invasion Targeted PlanetIDs: %s" %
          PlanetUtilsAI.planet_string(invasion_targeted_planet_ids))
    debug(invasion_fleet_ids and "Invasion Fleet IDs: %s" % invasion_fleet_ids
          or "Available Invasion Fleets: 0")
    debug("Invasion Fleets Without Missions: %s" % num_invasion_fleets)

    invasion_timer.start("planning troop base production")
    reserved_troop_base_targets = []
    if aistate.character.may_invade_with_bases():
        available_pp = {}
        for el in empire.planetsWithAvailablePP:  # keys are sets of ints; data is doubles
            avail_pp = el.data()
            for pid in el.key():
                available_pp[pid] = avail_pp
        # For planning base trooper invasion targets we have a two-pass system.  (1) In the first pass we consider all
        # the invasion targets and figure out which ones appear to be suitable for using base troopers against (i.e., we
        # already have a populated planet in the same system that could build base troopers) and we have at least a
        # minimal amount of PP available, and (2) in the second pass we go through the reserved base trooper target list
        # and check to make sure that there does not appear to be too much military action still needed before the
        # target is ready to be invaded, we double check that not too many base troopers would be needed, and if things
        # look clear then we queue up the base troopers on the Production Queue and keep track of where we are building
        # them, and how many; we may also disqualify and remove previously qualified targets (in case, for example,
        # we lost our base trooper source planet since it was first added to list).
        #
        # For planning and tracking base troopers under construction, we use a dictionary store in
        # get_aistate().qualifyingTroopBaseTargets, keyed by the invasion target planet ID.  We only store values
        # for invasion targets that appear likely to be suitable for base trooper use, and store a 2-item list.
        # The first item in this list is the ID of the planet where we expect to build the base troopers, and the second
        # entry initially is set to INVALID_ID (-1).  The presence of this entry in qualifyingTroopBaseTargets
        # flags this target as being reserved as a base-trooper invasion target.
        # In the second pass, if/when we actually start construction, then we modify the record, replacing that second
        # value with the ID of the planet where the troopers are actually being built.  (Right now that is always the
        # same as the source planet originally identified, but we could consider reevaluating that, or use that second
        # value to instead record how many base troopers have been queued, so that on later turns we can assess if the
        # process got delayed & perhaps more troopers need to be queued).

        # Pass 1: identify qualifying base troop invasion targets
        for pid in invadable_planet_ids:  # TODO: reorganize
            if pid in aistate.qualifyingTroopBaseTargets:
                continue
            planet = universe.getPlanet(pid)
            if not planet:
                continue
            sys_id = planet.systemID
            sys_partial_vis_turn = get_partial_visibility_turn(sys_id)
            planet_partial_vis_turn = get_partial_visibility_turn(pid)
            if planet_partial_vis_turn < sys_partial_vis_turn:
                continue
            best_base_planet = INVALID_ID
            best_trooper_count = 0
            for pid2 in get_colonized_planets_in_system(sys_id):
                if available_pp.get(
                        pid2, 0
                ) < 2:  # TODO: improve troop base PP sufficiency determination
                    break
                planet2 = universe.getPlanet(pid2)
                if not planet2 or not can_build_ship_for_species(
                        planet2.speciesName):
                    continue
                best_base_trooper_here = get_best_ship_info(
                    PriorityType.PRODUCTION_ORBITAL_INVASION, pid2)[1]
                if not best_base_trooper_here:
                    continue
                troops_per_ship = best_base_trooper_here.troopCapacity
                if not troops_per_ship:
                    continue
                species_troop_grade = get_species_tag_grade(
                    planet2.speciesName, Tags.ATTACKTROOPS)
                troops_per_ship = CombatRatingsAI.weight_attack_troops(
                    troops_per_ship, species_troop_grade)
                if troops_per_ship > best_trooper_count:
                    best_base_planet = pid2
                    best_trooper_count = troops_per_ship
            if best_base_planet != INVALID_ID:
                aistate.qualifyingTroopBaseTargets.setdefault(
                    pid, [best_base_planet, INVALID_ID])

        # Pass 2: for each target previously identified for base troopers, check that still qualifies and
        # check how many base troopers would be needed; if reasonable then queue up the troops and record this in
        # get_aistate().qualifyingTroopBaseTargets
        for pid in list(aistate.qualifyingTroopBaseTargets.keys()):
            planet = universe.getPlanet(pid)
            if planet and planet.owner == empire_id:
                del aistate.qualifyingTroopBaseTargets[pid]
                continue
            if pid in invasion_targeted_planet_ids:  # TODO: consider overriding standard invasion mission
                continue
            if aistate.qualifyingTroopBaseTargets[pid][1] != -1:
                reserved_troop_base_targets.append(pid)
                if planet:
                    all_invasion_targeted_system_ids.add(planet.systemID)
                # TODO: evaluate changes to situation, any more troops needed, etc.
                continue  # already building for here
            _, planet_troops = evaluate_invasion_planet(pid)
            sys_id = planet.systemID
            this_sys_status = aistate.systemStatus.get(sys_id, {})
            troop_tally = 0
            for _fid in this_sys_status.get("myfleets", []):
                troop_tally += FleetUtilsAI.count_troops_in_fleet(_fid)
            if troop_tally > planet_troops:  # base troopers appear unneeded
                del aistate.qualifyingTroopBaseTargets[pid]
                continue
            if planet.currentMeterValue(fo.meterType.shield) > 0 and (
                    this_sys_status.get("myFleetRating", 0) <
                    0.8 * this_sys_status.get("totalThreat", 0)
                    or this_sys_status.get("myFleetRatingVsPlanets", 0) <
                    this_sys_status.get("planetThreat", 0)):
                # this system not secured, so ruling out invasion base troops for now
                # don't immediately delete from qualifyingTroopBaseTargets or it will be opened up for regular troops
                continue
            loc = aistate.qualifyingTroopBaseTargets[pid][0]
            best_base_trooper_here = get_best_ship_info(
                PriorityType.PRODUCTION_ORBITAL_INVASION, loc)[1]
            loc_planet = universe.getPlanet(loc)
            if best_base_trooper_here is None:  # shouldn't be possible at this point, but just to be safe
                warning(
                    "Could not find a suitable orbital invasion design at %s" %
                    loc_planet)
                continue
            # TODO: have TroopShipDesigner give the expected number of troops including species effects directly
            troops_per_ship = best_base_trooper_here.troopCapacity
            species_troop_grade = get_species_tag_grade(
                loc_planet.speciesName, Tags.ATTACKTROOPS)
            troops_per_ship = CombatRatingsAI.weight_attack_troops(
                troops_per_ship, species_troop_grade)
            if not troops_per_ship:
                warning(
                    "The best orbital invasion design at %s seems not to have any troop capacity."
                    % loc_planet)
                continue
            _, col_design, build_choices = get_best_ship_info(
                PriorityType.PRODUCTION_ORBITAL_INVASION, loc)
            if not col_design:
                continue
            if loc not in build_choices:
                warning(
                    "Best troop design %s can not be produced at planet with id: %s"
                    % (col_design, build_choices))
                continue
            n_bases = math.ceil(
                (planet_troops + 1) /
                troops_per_ship)  # TODO: reconsider this +1 safety factor
            # TODO: evaluate cost and time-to-build of best base trooper here versus cost and time-to-build-and-travel
            # for best regular trooper elsewhere
            # For now, we assume what building base troopers is best so long as either (1) we would need no more than
            # MAX_BASE_TROOPERS_POOR_INVADERS base troop ships, or (2) our base troopers have more than 1 trooper per
            # ship and we would need no more than MAX_BASE_TROOPERS_GOOD_INVADERS base troop ships
            if n_bases > MAX_BASE_TROOPERS_POOR_INVADERS or (
                    troops_per_ship > 1
                    and n_bases > MAX_BASE_TROOPERS_GOOD_INVADERS):
                debug(
                    "ruling out base invasion troopers for %s due to high number (%d) required."
                    % (planet, n_bases))
                del aistate.qualifyingTroopBaseTargets[pid]
                continue
            debug(
                "Invasion base planning, need %d troops at %d per ship, will build %d ships."
                % ((planet_troops + 1), troops_per_ship, n_bases))
            retval = fo.issueEnqueueShipProductionOrder(col_design.id, loc)
            debug("Enqueueing %d Troop Bases at %s for %s" %
                  (n_bases, PlanetUtilsAI.planet_string(loc),
                   PlanetUtilsAI.planet_string(pid)))
            if retval != 0:
                all_invasion_targeted_system_ids.add(planet.systemID)
                reserved_troop_base_targets.append(pid)
                aistate.qualifyingTroopBaseTargets[pid][1] = loc
                fo.issueChangeProductionQuantityOrder(
                    empire.productionQueue.size - 1, 1, int(n_bases))
                fo.issueRequeueProductionOrder(empire.productionQueue.size - 1,
                                               0)

    invasion_timer.start("evaluating target planets")
    # TODO: check if any invasion_targeted_planet_ids need more troops assigned
    evaluated_planet_ids = list(
        set(invadable_planet_ids) - set(invasion_targeted_planet_ids) -
        set(reserved_troop_base_targets))
    evaluated_planets = assign_invasion_values(evaluated_planet_ids)

    sorted_planets = [(pid, pscore % 10000, ptroops)
                      for pid, (pscore, ptroops) in evaluated_planets.items()]
    sorted_planets.sort(key=lambda x: x[1], reverse=True)
    sorted_planets = [(pid, pscore % 10000, ptroops)
                      for pid, pscore, ptroops in sorted_planets]

    invasion_table = Table(
        Text("Planet"),
        Number("Score"),
        Text("Species"),
        Number("Troops"),
        table_name="Potential Targets for Invasion Turn %d" % fo.currentTurn(),
    )

    for pid, pscore, ptroops in sorted_planets:
        planet = universe.getPlanet(pid)
        invasion_table.add_row(planet, pscore, planet and planet.speciesName
                               or "unknown", ptroops)
    invasion_table.print_table(info)

    sorted_planets = [x for x in sorted_planets if x[1] > 0]
    # export opponent planets for other AI modules
    AIstate.opponentPlanetIDs = [pid for pid, __, __ in sorted_planets]
    AIstate.invasionTargets = sorted_planets

    # export invasion targeted systems for other AI modules
    AIstate.invasionTargetedSystemIDs = list(all_invasion_targeted_system_ids)
    invasion_timer.stop(section_name="evaluating %d target planets" %
                        (len(evaluated_planet_ids)))
    invasion_timer.stop_print_and_clear()
Esempio n. 58
0
def get_military_fleets(mil_fleets_ids=None, try_reset=True, thisround="Main"):
    """Get armed military fleets."""
    global _military_allocations

    universe = fo.getUniverse()
    empire_id = fo.empireID()
    home_system_id = PlanetUtilsAI.get_capital_sys_id()

    all_military_fleet_ids = (mil_fleets_ids if mil_fleets_ids is not None
                              else FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.MILITARY))

    if try_reset and (fo.currentTurn() + empire_id) % 30 == 0 and thisround == "Main":
        try_again(all_military_fleet_ids, try_reset=False, thisround=thisround + " Reset")
        return

    mil_fleets_ids = list(FleetUtilsAI.extract_fleet_ids_without_mission_types(all_military_fleet_ids))
    mil_needing_repair_ids, mil_fleets_ids = avail_mil_needing_repair(mil_fleets_ids, split_ships=True)
    avail_mil_rating = sum(map(CombatRatingsAI.get_fleet_rating, mil_fleets_ids))

    if not mil_fleets_ids:
        if "Main" in thisround:
            _military_allocations = []
        return []

    # for each system, get total rating of fleets assigned to it
    already_assigned_rating = {}
    already_assigned_rating_vs_planets = {}
    systems_status = foAI.foAIstate.systemStatus
    enemy_sup_factor = {}  # enemy supply
    for sys_id in universe.systemIDs:
        already_assigned_rating[sys_id] = 0
        already_assigned_rating_vs_planets[sys_id] = 0
        enemy_sup_factor[sys_id] = min(2, len(systems_status.get(sys_id, {}).get('enemies_nearly_supplied', [])))
    for fleet_id in [fid for fid in all_military_fleet_ids if fid not in mil_fleets_ids]:
        ai_fleet_mission = foAI.foAIstate.get_fleet_mission(fleet_id)
        if not ai_fleet_mission.target:  # shouldn't really be possible
            continue
        last_sys = ai_fleet_mission.target.get_system().id  # will count this fleet as assigned to last system in target list  # TODO last_sys or target sys?
        this_rating = CombatRatingsAI.get_fleet_rating(fleet_id)
        this_rating_vs_planets = CombatRatingsAI.get_fleet_rating_against_planets(fleet_id)
        already_assigned_rating[last_sys] = CombatRatingsAI.combine_ratings(
                already_assigned_rating.get(last_sys, 0), this_rating)
        already_assigned_rating_vs_planets[last_sys] = CombatRatingsAI.combine_ratings(
                already_assigned_rating_vs_planets.get(last_sys, 0), this_rating_vs_planets)
    for sys_id in universe.systemIDs:
        my_defense_rating = systems_status.get(sys_id, {}).get('mydefenses', {}).get('overall', 0)
        already_assigned_rating[sys_id] = CombatRatingsAI.combine_ratings(my_defense_rating, already_assigned_rating[sys_id])
        if _verbose_mil_reporting and already_assigned_rating[sys_id]:
            print "\t System %s already assigned rating %.1f" % (
                universe.getSystem(sys_id), already_assigned_rating[sys_id])

    # get systems to defend
    capital_id = PlanetUtilsAI.get_capital()
    if capital_id is not None:
        capital_planet = universe.getPlanet(capital_id)
    else:
        capital_planet = None
    # TODO: if no owned planets try to capture one!
    if capital_planet:
        capital_sys_id = capital_planet.systemID
    else:  # should be rare, but so as to not break code below, pick a randomish mil-centroid system
        capital_sys_id = None  # unless we can find one to use
        system_dict = {}
        for fleet_id in all_military_fleet_ids:
            status = foAI.foAIstate.fleetStatus.get(fleet_id, None)
            if status is not None:
                system_id = status['sysID']
                if not list(universe.getSystem(system_id).planetIDs):
                    continue
                system_dict[system_id] = system_dict.get(system_id, 0) + status.get('rating', 0)
        ranked_systems = sorted([(val, sys_id) for sys_id, val in system_dict.items()])
        if ranked_systems:
            capital_sys_id = ranked_systems[-1][-1]
        else:
            try:
                capital_sys_id = foAI.foAIstate.fleetStatus.items()[0][1]['sysID']
            except:
                pass

    num_targets = max(10, PriorityAI.allotted_outpost_targets)
    top_target_planets = ([pid for pid, pscore, trp in AIstate.invasionTargets[:PriorityAI.allotted_invasion_targets()]
                           if pscore > MIN_INVASION_SCORE] +
                          [pid for pid, (pscore, spec) in foAI.foAIstate.colonisableOutpostIDs.items()[:num_targets]
                           if pscore > MIN_INVASION_SCORE] +
                          [pid for pid, (pscore, spec) in foAI.foAIstate.colonisablePlanetIDs.items()[:num_targets]
                           if pscore > MIN_INVASION_SCORE])
    top_target_planets.extend(foAI.foAIstate.qualifyingTroopBaseTargets.keys())
    base_col_target_systems = PlanetUtilsAI.get_systems(top_target_planets)
    top_target_systems = []
    for sys_id in AIstate.invasionTargetedSystemIDs + base_col_target_systems:
        if sys_id not in top_target_systems:
            if foAI.foAIstate.systemStatus[sys_id]['totalThreat'] > get_tot_mil_rating():
                continue
            top_target_systems.append(sys_id)  # doing this rather than set, to preserve order

    try:
        # capital defense
        allocation_helper = AllocationHelper(already_assigned_rating, already_assigned_rating_vs_planets, avail_mil_rating, try_reset)
        if capital_sys_id is not None:
            CapitalDefenseAllocator(capital_sys_id, allocation_helper).allocate()

        # defend other planets
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)
        empire_occupied_system_ids = list(set(PlanetUtilsAI.get_systems(empire_planet_ids)) - {capital_sys_id})
        for sys_id in empire_occupied_system_ids:
            PlanetDefenseAllocator(sys_id, allocation_helper).allocate()

        # attack / protect high priority targets
        for sys_id in top_target_systems:
            TopTargetAllocator(sys_id, allocation_helper).allocate()

        # enemy planets
        other_targeted_system_ids = [sys_id for sys_id in set(PlanetUtilsAI.get_systems(AIstate.opponentPlanetIDs)) if
                                     sys_id not in top_target_systems]
        for sys_id in other_targeted_system_ids:
            TargetAllocator(sys_id, allocation_helper).allocate()

        # colony / outpost targets
        other_targeted_system_ids = [sys_id for sys_id in
                                     list(set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs)) if
                                     sys_id not in top_target_systems]
        for sys_id in other_targeted_system_ids:
            OutpostTargetAllocator(sys_id, allocation_helper).allocate()

        # TODO blockade enemy systems

        # interior systems
        targetable_ids = set(state.get_systems_by_supply_tier(0))
        current_mil_systems = [sid for sid, _, _, _, _ in allocation_helper.allocations]
        interior_targets1 = targetable_ids.difference(current_mil_systems)
        interior_targets = [sid for sid in interior_targets1 if (
            allocation_helper.threat_bias + systems_status.get(sid, {}).get('totalThreat', 0) > 0.8 * allocation_helper.already_assigned_rating[sid])]
        for sys_id in interior_targets:
            InteriorTargetsAllocator(sys_id, allocation_helper).allocate()

        # TODO Exploration targets

        # border protections
        visible_system_ids = foAI.foAIstate.visInteriorSystemIDs | foAI.foAIstate.visBorderSystemIDs
        accessible_system_ids = ([sys_id for sys_id in visible_system_ids if
                                 universe.systemsConnected(sys_id, home_system_id, empire_id)]
                                 if home_system_id != INVALID_ID else [])
        current_mil_systems = [sid for sid, alloc, rvp, take_any, _ in allocation_helper.allocations if alloc > 0]
        border_targets1 = [sid for sid in accessible_system_ids if sid not in current_mil_systems]
        border_targets = [sid for sid in border_targets1 if (
            allocation_helper.threat_bias + systems_status.get(sid, {}).get('fleetThreat', 0) + systems_status.get(sid, {}).get(
                    'planetThreat', 0) > 0.8 * allocation_helper.already_assigned_rating[sid])]
        for sys_id in border_targets:
            BorderSecurityAllocator(sys_id, allocation_helper).allocate()
    except ReleaseMilitaryException:
        try_again(all_military_fleet_ids)
        return

    new_allocations = []
    remaining_mil_rating = avail_mil_rating
    # for top categories assign max_alloc right away as available
    for cat in ['capitol', 'occupied', 'topTargets']:
        for sid, alloc, rvp, take_any, max_alloc in allocation_helper.allocation_by_groups.get(cat, []):
            if remaining_mil_rating <= 0:
                break
            this_alloc = min(remaining_mil_rating, max_alloc)
            new_allocations.append((sid, this_alloc, alloc, rvp, take_any))
            remaining_mil_rating -= this_alloc

    base_allocs = set()
    # for lower priority categories, first assign base_alloc around to all, then top up as available
    for cat in ['otherTargets', 'accessibleTargets', 'exploreTargets']:
        for sid, alloc, rvp, take_any, max_alloc in allocation_helper.allocation_by_groups.get(cat, []):
            if remaining_mil_rating <= 0:
                break
            base_allocs.add(sid)
            remaining_mil_rating -= alloc
    for cat in ['otherTargets', 'accessibleTargets', 'exploreTargets']:
        for sid, alloc, rvp, take_any, max_alloc in allocation_helper.allocation_by_groups.get(cat, []):
            if sid not in base_allocs:
                break
            if remaining_mil_rating <= 0:
                new_allocations.append((sid, alloc, alloc, rvp, take_any))
            else:
                new_rating = min(remaining_mil_rating + alloc, max_alloc)
                new_allocations.append((sid, new_rating, alloc, rvp, take_any))
                remaining_mil_rating -= (new_rating - alloc)

    if "Main" in thisround:
        _military_allocations = new_allocations
    if _verbose_mil_reporting or "Main" in thisround:
        print "------------------------------\nFinal %s Round Military Allocations: %s \n-----------------------" % (thisround, dict([(sid, alloc) for sid, alloc, _, _, _ in new_allocations]))
        print "(Apparently) remaining military rating: %.1f" % remaining_mil_rating

    return new_allocations
Esempio n. 59
0
def evaluate_invasion_planet(planet_id, secure_fleet_missions, verbose=True):
    """Return the invasion value (score, troops) of a planet."""
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    detail = []

    planet = universe.getPlanet(planet_id)
    if planet is None:
        print "Invasion AI couldn't access any info for planet id %d" % planet_id
        return [0, 0]

    system_id = planet.systemID

    # by using the following instead of simply relying on stealth meter reading, can (sometimes) plan ahead even if
    # planet is temporarily shrouded by an ion storm
    predicted_detectable = EspionageAI.colony_detectable_by_empire(
        planet_id, empire_id=fo.empireID(), default_result=False)
    if not predicted_detectable:
        if get_partial_visibility_turn(planet_id) < fo.currentTurn():
            debug("InvasionAI predicts planet id %d to be stealthed" %
                  planet_id)
            return [0, 0]
        else:
            debug(
                "InvasionAI predicts planet id %d to be stealthed" %
                planet_id +
                ", but somehow have current visibity anyway, will still consider as target"
            )

    # Check if the target planet was extra-stealthed somehow its system was last viewed
    # this test below may augment the tests above, but can be thrown off by temporary combat-related sighting
    system_last_seen = get_partial_visibility_turn(planet_id)
    planet_last_seen = get_partial_visibility_turn(system_id)
    if planet_last_seen < system_last_seen:
        # TODO: track detection strength, order new scouting when it goes up
        debug(
            "Invasion AI considering planet id %d (stealthed at last view), still proceeding."
            % planet_id)

    # get a baseline evaluation of the planet as determined by ColonisationAI
    species_name = planet.speciesName
    species = fo.getSpecies(species_name)
    if not species or AIDependencies.TAG_DESTROYED_ON_CONQUEST in species.tags:
        # this call iterates over this Empire's available species with which it could colonize after an invasion
        planet_eval = ColonisationAI.assign_colonisation_values(
            [planet_id], MissionType.INVASION, None, detail)
        colony_base_value = max(
            0.75 * planet_eval.get(planet_id, [0])[0],
            ColonisationAI.evaluate_planet(planet_id, MissionType.OUTPOST,
                                           None, detail))
    else:
        colony_base_value = ColonisationAI.evaluate_planet(
            planet_id, MissionType.INVASION, species_name, detail)

    # Add extra score for all buildings on the planet
    building_values = {
        "BLD_IMPERIAL_PALACE": 1000,
        "BLD_CULTURE_ARCHIVES": 1000,
        "BLD_AUTO_HISTORY_ANALYSER": 100,
        "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,
    }
    bld_tally = 0
    for bldType in [
            universe.getBuilding(bldg).buildingTypeName
            for bldg in planet.buildingIDs
    ]:
        bval = building_values.get(bldType, 50)
        bld_tally += bval
        detail.append("%s: %d" % (bldType, bval))

    # Add extra score for unlocked techs when we conquer the species
    tech_tally = 0
    value_per_pp = 4
    for unlocked_tech in AIDependencies.SPECIES_TECH_UNLOCKS.get(
            species_name, []):
        if not tech_is_complete(unlocked_tech):
            rp_cost = fo.getTech(unlocked_tech).researchCost(empire_id)
            tech_value = value_per_pp * rp_cost
            tech_tally += tech_value
            detail.append("%s: %d" % (unlocked_tech, tech_value))

    max_jumps = 8
    capitol_id = PlanetUtilsAI.get_capital()
    least_jumps_path = []
    clear_path = True
    if capitol_id:
        homeworld = universe.getPlanet(capitol_id)
        if homeworld and homeworld.systemID != INVALID_ID and system_id != INVALID_ID:
            least_jumps_path = list(
                universe.leastJumpsPath(homeworld.systemID, system_id,
                                        empire_id))
            max_jumps = len(least_jumps_path)
    system_status = foAI.foAIstate.systemStatus.get(system_id, {})
    system_fleet_treat = system_status.get('fleetThreat', 1000)
    system_monster_threat = system_status.get('monsterThreat', 0)
    sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get(
        'planetThreat', 0)
    max_path_threat = system_fleet_treat
    mil_ship_rating = MilitaryAI.cur_best_mil_ship_rating()
    for path_sys_id in least_jumps_path:
        path_leg_status = foAI.foAIstate.systemStatus.get(path_sys_id, {})
        path_leg_threat = path_leg_status.get(
            'fleetThreat', 1000) + path_leg_status.get('monsterThreat', 0)
        if path_leg_threat > 0.5 * mil_ship_rating:
            clear_path = False
            if path_leg_threat > max_path_threat:
                max_path_threat = path_leg_threat

    pop = planet.currentMeterValue(fo.meterType.population)
    target_pop = planet.currentMeterValue(fo.meterType.targetPopulation)
    troops = planet.currentMeterValue(fo.meterType.troops)
    troop_regen = planet.currentMeterValue(
        fo.meterType.troops) - planet.initialMeterValue(fo.meterType.troops)
    max_troops = planet.currentMeterValue(fo.meterType.maxTroops)
    # TODO: refactor troop determination into function for use in mid-mission updates and also consider defender techs
    max_troops += AIDependencies.TROOPS_PER_POP * (target_pop - pop)

    this_system = universe.getSystem(system_id)
    secure_targets = [system_id] + list(this_system.planetIDs)
    system_secured = False
    for mission in secure_fleet_missions:
        if system_secured:
            break
        secure_fleet_id = mission.fleet.id
        s_fleet = universe.getFleet(secure_fleet_id)
        if not s_fleet or s_fleet.systemID != system_id:
            continue
        if mission.type == MissionType.SECURE:
            target_obj = mission.target.get_object()
            if target_obj is not None and target_obj.id in secure_targets:
                system_secured = True
                break
    system_secured = system_secured and system_status.get('myFleetRating', 0)

    if verbose:
        print("Invasion eval of %s\n"
              " - maxShields: %.1f\n"
              " - sysFleetThreat: %.1f\n"
              " - sysMonsterThreat: %.1f") % (
                  planet, planet.currentMeterValue(fo.meterType.maxShield),
                  system_fleet_treat, system_monster_threat)
    enemy_val = 0
    if planet.owner != -1:  # value in taking this away from an enemy
        enemy_val = 20 * (
            planet.currentMeterValue(fo.meterType.targetIndustry) +
            2 * planet.currentMeterValue(fo.meterType.targetResearch))

    # devalue invasions that would require too much military force
    preferred_max_portion = MilitaryAI.get_preferred_max_military_portion_for_single_battle(
    )
    total_max_mil_rating = MilitaryAI.get_concentrated_tot_mil_rating()
    threat_exponent = 2  # TODO: make this a character trait; higher aggression with a lower exponent
    threat_factor = min(
        1, preferred_max_portion * total_max_mil_rating /
        (sys_total_threat + 0.001))**threat_exponent

    design_id, _, locs = ProductionAI.get_best_ship_info(
        PriorityType.PRODUCTION_INVASION)
    if not locs or not universe.getPlanet(locs[0]):
        # We are in trouble anyway, so just calculate whatever approximation...
        build_time = 4
        planned_troops = troops if system_secured else min(
            troops + troop_regen * (max_jumps + build_time), max_troops)
        planned_troops += .01  # we must attack with more troops than there are defenders
        troop_cost = math.ceil((planned_troops + _TROOPS_SAFETY_MARGIN) /
                               6.0) * 20 * FleetUtilsAI.get_fleet_upkeep()
    else:
        loc = locs[0]
        species_here = universe.getPlanet(loc).speciesName
        design = fo.getShipDesign(design_id)
        cost_per_ship = design.productionCost(empire_id, loc)
        build_time = design.productionTime(empire_id, loc)
        troops_per_ship = CombatRatingsAI.weight_attack_troops(
            design.troopCapacity,
            CombatRatingsAI.get_species_troops_grade(species_here))
        planned_troops = troops if system_secured else min(
            troops + troop_regen * (max_jumps + build_time), max_troops)
        planned_troops += .01  # we must attack with more troops than there are defenders
        ships_needed = math.ceil(
            (planned_troops + _TROOPS_SAFETY_MARGIN) / float(troops_per_ship))
        troop_cost = ships_needed * cost_per_ship  # fleet upkeep is already included in query from server

    # apply some bias to expensive operations
    normalized_cost = float(troop_cost) / max(fo.getEmpire().productionPoints,
                                              1)
    normalized_cost = max(1., normalized_cost)
    cost_score = (normalized_cost**2 / 50.0) * troop_cost

    base_score = colony_base_value + bld_tally + tech_tally + enemy_val - cost_score
    # If the AI does have enough total miltary to attack this target, and the target is more than minimally valuable,
    # don't let the threat_factor discount the adjusted value below MIN_INVASION_SCORE +1, so that if there are no
    # other targets the AI could still pursue this one.  Otherwise, scoring pressure from
    # MilitaryAI.get_preferred_max_military_portion_for_single_battle might prevent the AI from attacking heavily
    # defended but still defeatable targets even if it has no softer targets available.
    if total_max_mil_rating > sys_total_threat and base_score > 2 * MIN_INVASION_SCORE:
        threat_factor = max(threat_factor,
                            (MIN_INVASION_SCORE + 1) / base_score)
    planet_score = retaliation_risk_factor(planet.owner) * threat_factor * max(
        0, base_score)
    if clear_path:
        planet_score *= 1.5
    if verbose:
        print(' - planet score: %.2f\n'
              ' - planned troops: %.2f\n'
              ' - projected troop cost: %.1f\n'
              ' - threat factor: %s\n'
              ' - planet detail: %s\n'
              ' - popval: %.1f\n'
              ' - bldval: %s\n'
              ' - enemyval: %s') % (planet_score, planned_troops, troop_cost,
                                    threat_factor, detail, colony_base_value,
                                    bld_tally, enemy_val)
    return [planet_score, planned_troops]