示例#1
0
def assign_invasion_values(planet_ids, mission_type, fleet_suppliable_planet_ids, empire):
    """Creates a dictionary that takes planet_ids as key and their invasion score as value."""
    planet_values = {}
    neighbor_values = {}
    neighbor_val_ratio = .95
    universe = fo.getUniverse()
    secure_missions = foAI.foAIstate.get_fleet_missions_with_any_mission_types([EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE])
    for pid in planet_ids:
        planet_values[pid] = neighbor_values.setdefault(pid, evaluate_invasion_planet(pid, empire, secure_missions))
        print "planet %d, values %s" % (pid, planet_values[pid])
        planet = universe.getPlanet(pid)
        species_name = (planet and planet.speciesName) or ""
        species = fo.getSpecies(species_name)
        if species and species.canProduceShips:
            system = universe.getSystem(planet.systemID)
            if not system:
                continue
            planet_industries = {}
            for pid2 in system.planetIDs:
                planet2 = universe.getPlanet(pid2)
                species_name2 = (planet2 and planet2.speciesName) or ""
                species2 = fo.getSpecies(species_name2)
                if species2 and species2.canProduceShips:
                    planet_industries[pid2] = planet2.currentMeterValue(fo.meterType.industry) + 0.1  # to prevent divide-by-zero
            industry_ratio = planet_industries[pid] / max(planet_industries.values())
            for pid2 in system.planetIDs:
                if pid2 == pid:
                    continue
                planet2 = universe.getPlanet(pid2)
                if planet2 and (planet2.owner != empire.empireID) and ((planet2.owner != -1) or (planet.currentMeterValue(fo.meterType.population) > 0)):  # TODO check for allies
                    planet_values[pid][0] += industry_ratio * neighbor_val_ratio * (neighbor_values.setdefault(pid2, evaluate_invasion_planet(pid2, empire, secure_missions))[0])
    return planet_values
示例#2
0
def assign_invasion_values(planet_ids, mission_type, fleet_suppliable_planet_ids, empire):
    """Creates a dictionary that takes planet_ids as key and their invasion score as value."""
    planet_values = {}
    neighbor_values = {}
    neighbor_val_ratio = .95
    universe = fo.getUniverse()
    secure_missions = foAI.foAIstate.get_fleet_missions_with_any_mission_types([EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE])
    for pid in planet_ids:
        planet_values[pid] = neighbor_values.setdefault(pid, evaluate_invasion_planet(pid, empire, secure_missions))
        print "planet %d, values %s" % (pid, planet_values[pid])
        planet = universe.getPlanet(pid)
        species_name = (planet and planet.speciesName) or ""
        species = fo.getSpecies(species_name)
        if species and species.canProduceShips:
            system = universe.getSystem(planet.systemID)
            if not system:
                continue
            planet_industries = {}
            for pid2 in system.planetIDs:
                planet2 = universe.getPlanet(pid2)
                species_name2 = (planet2 and planet2.speciesName) or ""
                species2 = fo.getSpecies(species_name2)
                if species2 and species2.canProduceShips:
                    planet_industries[pid2] = planet2.currentMeterValue(fo.meterType.industry) + 0.1  # to prevent divide-by-zero
            industry_ratio = planet_industries[pid] / max(planet_industries.values())
            for pid2 in system.planetIDs:
                if pid2 == pid:
                    continue
                planet2 = universe.getPlanet(pid2)
                if planet2 and (planet2.owner != empire.empireID) and ((planet2.owner != -1) or (planet.currentMeterValue(fo.meterType.population) > 0)):  # TODO check for allies
                    planet_values[pid][0] += industry_ratio * neighbor_val_ratio * (neighbor_values.setdefault(pid2, evaluate_invasion_planet(pid2, empire, secure_missions))[0])
    return planet_values
示例#3
0
def _calculate_get_planet_opinions() -> Dict[str, Opinion]:
    universe = fo.getUniverse()
    all_species = [
        universe.getPlanet(pid).speciesName
        for pid in get_owned_planets_by_empire()
    ]
    all_species += get_extra_colony_builders()
    all_features = set()
    for species_name in all_species:
        if species_name:
            species = fo.getSpecies(species_name)
            all_features.update(species.likes)
            all_features.update(species.dislikes)

    result = {
        feature: Opinion(set(), set(), set())
        for feature in all_features
    }
    for pid in get_owned_planets_by_empire():
        species = _planet_species(pid)
        for feature, opinion in result.items():
            if species:
                if feature in species.likes:
                    opinion.likes.add(pid)
                elif feature in species.dislikes:
                    opinion.dislikes.add(pid)
                else:
                    opinion.neutral.add(pid)
            # else: no species -> neutral
            opinion.neutral.add(pid)
    return result
示例#4
0
def test_calc_max_pop():
    """
    Verify AI calculation of max population by comparing it with actual client
    queried values.

    This function may be called in debug mode in a running game and will compare
    the actual target population meters on all planets owned by this AI with the
    predicted maximum population. Any mismatch will be reported in chat.
    """
    from freeorion_tools import chat_human

    chat_human("Verifying calculation of ColonisationAI.calc_max_pop()")
    universe = fo.getUniverse()
    for spec_name, planets in get_empire_planets_by_species().items():
        species = fo.getSpecies(spec_name)
        for pid in planets:
            planet = universe.getPlanet(pid)
            detail = []
            predicted = calc_max_pop(planet, species, detail)
            actual = planet.initialMeterValue(fo.meterType.targetPopulation)
            if actual != predicted:
                error(
                    "Predicted pop of %.2f on %s but actually is %.2f; Details: %s"
                    % (predicted, planet, actual, "\n".join(detail))
                )
    chat_human("Finished verification of ColonisationAI.calc_max_pop()")
示例#5
0
 def get_piloting_grades(self,  species_name):
     if species_name in piloting_grades:
         return piloting_grades[species_name]
     weapons_grade=""
     shields_grade=""
     if species_name == "":
         spec_tags = []
     else:
         species = fo.getSpecies(species_name)
         if species:
             spec_tags = species.tags
         else:
             print "Error: get_piloting_grades couldn't retrieve species '%s'" % species_name
             spec_tags = []
     for tag in spec_tags:
         if "AI_TAG" not in tag:
             continue
         tag_parts = tag.split('_')
         tag_type = tag_parts[3]
         if tag_type == 'WEAPONS':
             weapons_grade = tag_parts[2]
         elif tag_type == 'SHIELDS':
             shields_grade = tag_parts[2]
     piloting_grades[species_name] = (weapons_grade,  shields_grade)
     return (weapons_grade,  shields_grade)
示例#6
0
def assign_invasion_values(planet_ids):
    """Creates a dictionary that takes planet_ids as key and their invasion score as value."""
    empire_id = fo.empireID()
    planet_values = {}
    neighbor_values = {}
    neighbor_val_ratio = .95
    universe = fo.getUniverse()
    secure_missions = get_aistate().get_fleet_missions_with_any_mission_types(
        [MissionType.SECURE, MissionType.MILITARY])
    for pid in planet_ids:
        planet_values[pid] = neighbor_values.setdefault(
            pid, evaluate_invasion_planet(pid, secure_missions))
        debug("planet %d, values %s", pid, planet_values[pid])
        planet = universe.getPlanet(pid)
        species_name = (planet and planet.speciesName) or ""
        species = fo.getSpecies(species_name)
        if species and species.canProduceShips:
            system = universe.getSystem(planet.systemID)
            if not system:
                continue
            planet_industries = {}
            for pid2 in system.planetIDs:
                planet2 = universe.getPlanet(pid2)
                species_name2 = (planet2 and planet2.speciesName) or ""
                species2 = fo.getSpecies(species_name2)
                if species2 and species2.canProduceShips:
                    # to prevent divide-by-zero
                    planet_industries[pid2] = planet2.initialMeterValue(
                        fo.meterType.industry) + 0.1
            industry_ratio = planet_industries[pid] / max(
                planet_industries.values())
            for pid2 in system.planetIDs:
                if pid2 == pid:
                    continue
                planet2 = universe.getPlanet(pid2)
                # TODO check for allies
                if (planet2 and (planet2.owner != empire_id) and (
                    (planet2.owner != -1) or
                    (planet2.initialMeterValue(fo.meterType.population) > 0))):
                    planet_values[pid][0] += (
                        industry_ratio * neighbor_val_ratio *
                        (neighbor_values.setdefault(
                            pid2,
                            evaluate_invasion_planet(pid2,
                                                     secure_missions))[0]))
    return planet_values
示例#7
0
def get_species_tag_grade(species_name, tag_type):
    if not species_name:
        return ""
    species = fo.getSpecies(species_name)
    if assertion_fails(species is not None):
        return ""

    return get_ai_tag_grade(species.tags, tag_type)
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.
示例#10
0
def _get_species_grades(species_name, grade_type):
    spec_tags = []
    if species_name:
        species = fo.getSpecies(species_name)
        if species:
            spec_tags = species.tags
        else:
            print >> sys.stderr, "get_species_grades() couldn't retrieve species '%s'\n" % species_name
    return get_ai_tag_grade(spec_tags, grade_type)
def _get_species_grades(species_name, grade_type):
    spec_tags = []
    if species_name:
        species = fo.getSpecies(species_name)
        if species:
            spec_tags = species.tags
        else:
            print >> sys.stderr, "get_species_grades() couldn't retrieve species '%s'\n" % species_name
    return get_ai_tag_grade(spec_tags, grade_type)
示例#12
0
def _get_species_grades(species_name, grade_type):
    spec_tags = []
    if species_name:
        species = fo.getSpecies(species_name)
        if species:
            spec_tags = species.tags
        else:
            warn("get_species_grades() couldn't retrieve species '%s'\n" % species_name)
    return get_ai_tag_grade(spec_tags, grade_type)
示例#13
0
def _get_species_grades(species_name, grade_type):
    spec_tags = []
    if species_name:
        species = fo.getSpecies(species_name)
        if species:
            spec_tags = species.tags
        else:
            sys.stderr.write("Error: get_species_grades couldn't retrieve species '%s'\n" % species_name)
    return get_ai_tag_grade(spec_tags, grade_type)
示例#14
0
def _planet_species(pid: PlanetId) -> Optional[fo.species]:
    universe = fo.getUniverse()
    planet = universe.getPlanet(pid)
    species_name = planet.speciesName
    if not species_name:
        species_name = _planned_species().get(pid)
    if species_name:
        return fo.getSpecies(species_name)
    return None
示例#15
0
def _get_species_grades(species_name, grade_type):
    spec_tags = []
    if species_name:
        species = fo.getSpecies(species_name)
        if species:
            spec_tags = species.tags
        else:
            warn("get_species_grades() couldn't retrieve species '%s'\n" %
                 species_name)
    return get_ai_tag_grade(spec_tags, grade_type)
示例#16
0
def get_species_tag_grade(species_name: str,
                          tag_type: AIDependencies.Tags) -> str:
    """Determine grade string ("NO", "BAD", "GOOD", etc.), if any, for given tag and species."""
    if not species_name:
        return ""
    species = fo.getSpecies(species_name)
    if assertion_fails(species is not None):
        return ""

    return get_ai_tag_grade(species.tags, tag_type)
示例#17
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
示例#18
0
def assign_invasion_values(planet_ids):
    """Creates a dictionary that takes planet_ids as key and their invasion score as value."""
    empire_id = fo.empireID()
    planet_values = {}
    neighbor_values = {}
    neighbor_val_ratio = .95
    universe = fo.getUniverse()
    secure_missions = get_aistate().get_fleet_missions_with_any_mission_types([MissionType.SECURE,
                                                                               MissionType.MILITARY])
    for pid in planet_ids:
        planet_values[pid] = neighbor_values.setdefault(pid, evaluate_invasion_planet(pid, secure_missions))
        debug("planet %d, values %s", pid, planet_values[pid])
        planet = universe.getPlanet(pid)
        species_name = (planet and planet.speciesName) or ""
        species = fo.getSpecies(species_name)
        if species and species.canProduceShips:
            system = universe.getSystem(planet.systemID)
            if not system:
                continue
            planet_industries = {}
            for pid2 in system.planetIDs:
                planet2 = universe.getPlanet(pid2)
                species_name2 = (planet2 and planet2.speciesName) or ""
                species2 = fo.getSpecies(species_name2)
                if species2 and species2.canProduceShips:
                    # to prevent divide-by-zero
                    planet_industries[pid2] = planet2.initialMeterValue(fo.meterType.industry) + 0.1
            industry_ratio = planet_industries[pid] / max(planet_industries.values())
            for pid2 in system.planetIDs:
                if pid2 == pid:
                    continue
                planet2 = universe.getPlanet(pid2)
                # TODO check for allies
                if (planet2 and (planet2.owner != empire_id) and
                        ((planet2.owner != -1) or (planet2.initialMeterValue(fo.meterType.population) > 0))):
                    planet_values[pid][0] += (
                        industry_ratio *
                        neighbor_val_ratio *
                        (neighbor_values.setdefault(pid2, evaluate_invasion_planet(pid2, secure_missions))[0])
                    )
    return planet_values
示例#19
0
def stability_with_focus(planet: fo.planet, focus: str) -> float:
    """
    What would the planets target stability be when switched to the given focus.
    Returns -99 if species cannot use the specified focus.
    """
    stability = planet.currentMeterValue(fo.meterType.targetHappiness)
    species = fo.getSpecies(planet.speciesName)
    if focus not in species.foci:
        # The actual value here is not important. If some part of the AI asks for a stability,
        # returning a big negative value here should stop it from considering that focus for anything.
        return -99.0
    return stability - focus_stability_effect(
        species, planet.focus) + focus_stability_effect(species, focus)
示例#20
0
def assignColonisationValues(planetIDs, missionType, fleetSupplyablePlanetIDs, species, empire):
    "creates a dictionary that takes planetIDs as key and their colonisation score as value"

    planetValues = {}
    for planetID in planetIDs:
        pv = []
        for specName in empireColonizers:
            thisSpecies=fo.getSpecies(specName)
            pv.append( (evaluatePlanet(planetID, missionType, fleetSupplyablePlanetIDs, thisSpecies, empire),  specName) )
        best = sorted(pv)[-1:]
        if best!=[]:
            if   (missionType == AIFleetMissionType.FLEET_MISSION_OUTPOST ):
                planetValues[planetID] = (best[0][0],  "")
            else:
                planetValues[planetID] = best[0]

    return planetValues
示例#21
0
def assignColonisationValues(planetIDs, missionType, fleetSupplyablePlanetIDs, species, empire): #TODO: clean up supplyable versus annexable
    "creates a dictionary that takes planetIDs as key and their colonisation score as value"

    planetValues = {}
    for planetID in planetIDs:
        pv = []
        for specName in empireColonizers:
            thisSpecies=fo.getSpecies(specName)
            pv.append( (evaluatePlanet(planetID, missionType, fleetSupplyablePlanetIDs, thisSpecies, empire),  specName) )
        best = sorted(pv)[-1:]
        if best!=[]:
            if   (missionType == AIFleetMissionType.FLEET_MISSION_OUTPOST ):
                planetValues[planetID] = (best[0][0],  "")
            else:#TODO: check for system-local colonizer; also,  if a tie amongst top try to choose empire main species
                planetValues[planetID] = best[0]

    return planetValues
示例#22
0
 def _rate_artisans(self) -> float:
     """Rate artisan workshops."""
     # Diversity unlocks artisans, so if we have diversity, we could unlock artisans
     if diversity not in self._empire.availablePolicies:
         return 0.0
     # TBD: could use _calculate_empire_output, but we'd still have to check the species, since artistic
     # species may not be switched to influence.
     rating = 0.0
     artists = []
     for species_name, planets in get_empire_planets_by_species().items():
         species = fo.getSpecies(species_name)
         if Tags.ARTISTIC in species.tags:
             artists.append(species_name)
             for pid in planets:
                 rating += self._rate_artisan_planet(pid, species_name)
     rating += self._rate_opinion(artisans)
     debug(f"_rate_artisans: {rating}, artists: {artists}")
     return rating
示例#23
0
def _print_empire_species_roster():
    """Print empire species roster in table format to log."""
    grade_map = {"ULTIMATE": "+++", "GREAT": "++", "GOOD": "+", "AVERAGE": "o", "BAD": "-", "NO": "---"}

    grade_tags = [
        Tags.INDUSTRY,
        Tags.RESEARCH,
        Tags.POPULATION,
        Tags.SUPPLY,
        Tags.WEAPONS,
        Tags.ATTACKTROOPS,
    ]

    grade_tags_names = {
        Tags.INDUSTRY: "Ind.",
        Tags.RESEARCH: "Res.",
        Tags.POPULATION: "Pop.",
        Tags.SUPPLY: "Supply",
        Tags.WEAPONS: "Pilot",
        Tags.ATTACKTROOPS: "Troop",
    }

    species_table = Table(
        Text("species"),
        Sequence("PIDs"),
        Bool("Colonize"),
        Text("Shipyards"),
        *[Text(grade_tags_names[v]) for v in grade_tags],
        Sequence("Tags"),
        table_name="Empire species roster Turn %d" % fo.currentTurn(),
    )
    for species_name, planet_ids in get_empire_planets_by_species().items():
        species_tags = fo.getSpecies(species_name).tags
        number_of_shipyards = len(get_ship_builder_locations(species_name))
        species_table.add_row(
            species_name,
            planet_ids,
            can_build_colony_for_species(species_name),
            number_of_shipyards,
            *[grade_map.get(get_species_tag_grade(species_name, tag).upper(), "o") for tag in grade_tags],
            [tag for tag in species_tags if not any(s in tag for s in grade_tags) and "PEDIA" not in tag],
        )
    species_table.print_table(info)
示例#24
0
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire):
    "return the invasion value of a planet"
    #TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empireID = empire.empireID
    distanceFactor = 0
    planet = universe.getPlanet(planetID)
    if (planet == None) :  #TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't get current info on planet %d"%planetID
        return 0, 0
        
    capitalID = PlanetUtilsAI.getCapital()
    homeworld = universe.getPlanet(capitalID)
    if homeworld:
        homeSystemID = homeworld.systemID
        evalSystemID = planet.systemID
        leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID))
        distanceFactor = 4.0/(leastJumpsPath + 1)
        
    troops = planet.currentMeterValue(fo.meterType.troops)
    specName=planet.speciesName
    species=fo.getSpecies(specName)
    if not species:# perhaps stealth might make species info inaccessible
        targetPop=planet.currentMeterValue(fo.meterType.targetPopulation)
        if planetID in fleetSupplyablePlanetIDs:
            popVal =  4*targetPop
        else:
            popVal =  6*targetPop#assign higher value if the colony would extend our supply range
        planetSpecials = list(planet.specials)
        specialVal=0
        if  ( ( planet.size  ==  fo.planetSize.asteroids ) and  (empire.getTechStatus("PRO_ASTEROID_MINE") == fo.techStatus.complete ) ): 
                specialVal= 15   # asteroid mining is great, fast return
        for special in [ "MINERALS_SPECIAL",  "CRYSTALS_SPECIAL",  "METALOIDS_SPECIAL"] :
            if special in planetSpecials:
                specialVal = 40 
        return popVal+specialVal,  troops
    else:
        popVal = evaluatePlanet(planetID,  AIFleetMissionType.FLEET_MISSION_COLONISATION,  [planetID],  species,  empire) #evaluatePlanet is implorted from ColonisationAI
        if planetID not in fleetSupplyablePlanetIDs:
            popVal =  2.0*popVal#assign higher value if the colony would extend our supply range
        return popVal,  troops
示例#25
0
def assignColonisationValues(planetIDs, missionType, fleetSupplyablePlanetIDs, species, empire,  detail=[]): #TODO: clean up supplyable versus annexable
    "creates a dictionary that takes planetIDs as key and their colonisation score as value"
    origDetail = detail
    planetValues = {}
    if   (missionType == AIFleetMissionType.FLEET_MISSION_OUTPOST ):
        print "\n=========\nAssigning Outpost Values\n========="
        trySpecies = [ "" ]
    else:
        print "\n=========\nAssigning Colony Values\n========="
        trySpecies = list(  empireColonizers  )
    for planetID in planetIDs:
        pv = []
        for specName in trySpecies:
            thisSpecies=fo.getSpecies(specName)
            detail = origDetail[:]
            pv.append( (evaluatePlanet(planetID, missionType, fleetSupplyablePlanetIDs, thisSpecies, empire,  detail),  specName,  list(detail)) )
        best = sorted(pv)[-1:]
        if best!=[]:
            planetValues[planetID] = best[0][:2]
            print best[0][2]
    return planetValues
示例#26
0
    def is_valid(self) -> bool:
        """
        Check the colonization plan for validity, i.e. if it could be executed in the future.

        The plan is valid if it is possible to outpost the target planet
        and if the planet envisioned to build the outpost bases can still do so.
        """
        universe = fo.getUniverse()

        # make sure target is valid
        target = universe.getPlanet(self.target)
        if target is None or (not target.unowned) or target.speciesName:
            return False

        # make sure source is valid
        source = universe.getPlanet(self.source)
        if not (source and source.ownedBy(fo.empireID()) and source.speciesName
                and fo.getSpecies(source.speciesName).canColonize):
            return False

        # appears to be valid
        return True
示例#27
0
def assignInvasionValues(planetIDs, missionType, fleetSupplyablePlanetIDs, empire):
    "creates a dictionary that takes planetIDs as key and their invasion score as value"

    planetValues = {}
    neighbor_values = {}
    universe = fo.getUniverse()    
    secureAIFleetMissions = foAI.foAIstate.getAIFleetMissionsWithAnyMissionTypes([EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE])
    for planetID in planetIDs:
        planetValues[planetID] = neighbor_values.setdefault(planetID, evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire,  secureAIFleetMissions))
        print "planet %d,  values %s"%(planetID,  planetValues[planetID])
        planet = universe.getPlanet(planetID)
        specName = (planet and planet.speciesName) or ""
        species = fo.getSpecies(specName)
        if species and species.canProduceShips:
            system = universe.getSystem(planet.systemID)
            if not system:
                continue
            for pid2 in system.planetIDs:
                if pid2 == planetID:
                    continue
                planet2 = universe.getPlanet(pid2)
                if planet2 and (planet2.owner != empire.empireID) and ((planet2.owner != -1) or (planet.currentMeterValue(fo.meterType.population) > 0)): #TODO check for allies
                    planetValues[planetID][0] += 0.5 * (neighbor_values.setdefault( pid2, evaluateInvasionPlanet(pid2, missionType, fleetSupplyablePlanetIDs, empire,  secureAIFleetMissions))[0])
    return planetValues
示例#28
0
def evaluate_invasion_planet(planet_id, secure_fleet_missions, verbose=True):
    """Return the invasion value (score, troops) of a planet."""
    detail = []
    building_values = {"BLD_IMPERIAL_PALACE": 1000,
                       "BLD_CULTURE_ARCHIVES": 1000,
                       "BLD_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,
                       }
    # TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    max_jumps = 8
    planet = universe.getPlanet(planet_id)
    if planet is None:  # TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't access any info for planet id %d" % planet_id
        return [0, 0]

    sys_partial_vis_turn = get_partial_visibility_turn(planet.systemID)
    planet_partial_vis_turn = get_partial_visibility_turn(planet_id)

    if planet_partial_vis_turn < sys_partial_vis_turn:
        print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id
        # TODO: track detection strength, order new scouting when it goes up
        return [0, 0]  # last time we had partial vis of the system, the planet was stealthed to us

    species_name = planet.speciesName
    species = fo.getSpecies(species_name)
    if not species 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)
        pop_val = max(0.75 * planet_eval.get(planet_id, [0])[0],
                      ColonisationAI.evaluate_planet(planet_id, MissionType.OUTPOST, None, detail))
    else:
        pop_val = ColonisationAI.evaluate_planet(planet_id, MissionType.INVASION, species_name, detail)

    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))

    tech_tally = 0
    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_tally += rp_cost * 4
            detail.append("%s: %d" % (unlocked_tech, rp_cost * 4))

    p_sys_id = planet.systemID
    capitol_id = PlanetUtilsAI.get_capital()
    least_jumps_path = []
    clear_path = True
    if capitol_id:
        homeworld = universe.getPlanet(capitol_id)
        if homeworld:
            home_system_id = homeworld.systemID
            eval_system_id = planet.systemID
            if (home_system_id != INVALID_ID) and (eval_system_id != INVALID_ID):
                least_jumps_path = list(universe.leastJumpsPath(home_system_id, eval_system_id, empire_id))
                max_jumps = len(least_jumps_path)
    system_status = foAI.foAIstate.systemStatus.get(p_sys_id, {})
    system_fleet_treat = system_status.get('fleetThreat', 1000)
    system_monster_threat = system_status.get('monsterThreat', 0)
    sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get('planetThreat', 0)
    max_path_threat = system_fleet_treat
    mil_ship_rating = 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)
    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(p_sys_id)
    secure_targets = [p_sys_id] + list(this_system.planetIDs)
    system_secured = False
    for mission in secure_fleet_missions:
        if system_secured:
            break
        secure_fleet_id = mission.fleet.id
        s_fleet = universe.getFleet(secure_fleet_id)
        if not s_fleet or s_fleet.systemID != p_sys_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)
    supply_val = 0
    enemy_val = 0
    if planet.owner != -1:  # value in taking this away from an enemy
        enemy_val = 20 * (planet.currentMeterValue(fo.meterType.targetIndustry) +
                          2*planet.currentMeterValue(fo.meterType.targetResearch))
    if p_sys_id in ColonisationAI.annexable_system_ids:  # TODO: extend to rings
        supply_val = 100
    elif p_sys_id in state.get_systems_by_supply_tier(-1):
        supply_val = 200
    elif p_sys_id in state.get_systems_by_supply_tier(-2):
        supply_val = 300
    elif p_sys_id in state.get_systems_by_supply_tier(-3):
        supply_val = 400
    if max_path_threat > 0.5 * mil_ship_rating:
        if max_path_threat < 3 * mil_ship_rating:
            supply_val *= 0.5
        else:
            supply_val *= 0.2

    # devalue invasions that would require too much military force
    threat_factor = min(1, 0.2*MilitaryAI.get_tot_mil_rating()/(sys_total_threat+0.001))**2

    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 + 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 + 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 = pop_val + supply_val + bld_tally + tech_tally + enemy_val - cost_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'
               ' - troop score: %.2f\n'
               ' - projected troop cost: %.1f\n'
               ' - threat factor: %s\n'
               ' - planet detail: %s\n'
               ' - popval: %.1f\n'
               ' - supplyval: %.1f\n'
               ' - bldval: %s\n'
               ' - enemyval: %s') % (planet_score, planned_troops, troop_cost,
                                     threat_factor, detail, pop_val, supply_val, bld_tally, enemy_val)
    return [planet_score, planned_troops]
示例#29
0
def generate_classic_research_orders():
    """generate research orders"""
    empire = fo.getEmpire()
    empire_id = empire.empireID
    aistate = get_aistate()
    enemies_sighted = aistate.misc.get("enemies_sighted", {})
    galaxy_is_sparse = ColonisationAI.galaxy_is_sparse()

    resource_production = empire.resourceProduction(fo.resourceType.research)
    completed_techs = sorted(list(get_completed_techs()))
    _print_reserch_order_header(resource_production, completed_techs)

    #
    # report techs currently at head of research queue
    #
    research_queue = empire.researchQueue
    research_queue_list = get_research_queue_techs()
    total_rp = empire.resourceProduction(fo.resourceType.research)
    tech_turns_left = {}
    if research_queue_list:
        debug("Techs currently at head of Research Queue:")
        for element in list(research_queue)[:10]:
            tech_turns_left[element.tech] = element.turnsLeft
            this_tech = fo.getTech(element.tech)
            if not this_tech:
                warning("Can't retrieve tech ", element.tech)
                continue
            missing_prereqs = [
                preReq
                for preReq in this_tech.recursivePrerequisites(empire_id)
                if preReq not in completed_techs
            ]
            # unlocked_items = [(uli.name, uli.type) for uli in this_tech.unlocked_items]
            unlocked_items = [uli.name for uli in this_tech.unlockedItems]
            if not missing_prereqs:
                debug(
                    "    %25s allocated %6.2f RP (%d turns left)-- unlockable items: %s ",
                    element.tech,
                    element.allocation,
                    tech_turns_left[element.tech],
                    unlocked_items,
                )
            else:
                debug(
                    "    %25s allocated %6.2f RP -- missing preReqs: %s -- unlockable items: %s ",
                    element.tech,
                    element.allocation,
                    missing_prereqs,
                    unlocked_items,
                )
        debug("")
    #
    # set starting techs, or after turn 100 add any additional default techs
    #
    if (fo.currentTurn() <= 2) or ((total_rp - research_queue.totalSpent) > 0):
        research_index = get_research_index()
        if fo.currentTurn() == 1:
            # do only this one on first turn, to facilitate use of a turn-1 savegame for testing of alternate
            # research strategies
            new_tech = ["LRN_PHYS_BRAIN", "GRO_PLANET_ECOL"]
        else:
            new_tech = (TechsListsAI.sparse_galaxy_techs(research_index)
                        if galaxy_is_sparse else
                        TechsListsAI.primary_meta_techs(research_index))
        debug("Empire %s (%d) is selecting research index %d", empire.name,
              empire_id, research_index)
        # techs_to_enqueue = (set(new_tech)-(set(completed_techs)|set(research_queue_list)))
        techs_to_enqueue = new_tech[:]
        tech_base = set(completed_techs + research_queue_list)
        techs_to_add = []
        for tech in techs_to_enqueue:
            if tech not in tech_base:
                this_tech = fo.getTech(tech)
                if this_tech is None:
                    error("Desired tech '%s' appears to not exist" % tech)
                    continue
                missing_prereqs = [
                    preReq
                    for preReq in this_tech.recursivePrerequisites(empire_id)
                    if preReq not in tech_base
                ]
                techs_to_add.extend(missing_prereqs + [tech])
                tech_base.update(missing_prereqs + [tech])
        cum_cost = 0
        debug("  Enqueued Tech: %20s \t\t %8s \t %s", "Name", "Cost",
              "CumulativeCost")
        for name in techs_to_add:
            try:
                enqueue_res = fo.issueEnqueueTechOrder(name, -1)
                if enqueue_res == 1:
                    this_tech = fo.getTech(name)
                    this_cost = 0
                    if this_tech:
                        this_cost = this_tech.researchCost(empire_id)
                        cum_cost += this_cost
                    debug("    Enqueued Tech: %20s \t\t %8.0f \t %8.0f", name,
                          this_cost, cum_cost)
                else:
                    warning("    Failed attempt to enqueued Tech: " + name)
            except:  # noqa: E722
                warning("    Failed attempt to enqueued Tech: " + name,
                        exc_info=True)

        debug("\n\nAll techs:")
        debug("=" * 20)
        alltechs = fo.techs()
        print_in_columns(sorted(fo.techs()), columns=3)

        debug("\n\nAll unqueued techs:")
        debug("=" * 20)
        # coveredTechs = new_tech+completed_techs
        print_in_columns([tn for tn in alltechs if tn not in tech_base],
                         columns=3)
        debug("")

        if fo.currentTurn() == 1:
            return
        if True:
            research_queue_list = get_research_queue_techs()
            def_techs = TechsListsAI.defense_techs_1()
            for def_tech in def_techs:
                if (aistate.character.may_research_tech_classic(def_tech)
                        and def_tech not in research_queue_list[:5]
                        and not tech_is_complete(def_tech)):
                    res = fo.issueEnqueueTechOrder(
                        def_tech, min(3, len(research_queue_list)))
                    debug(
                        "Empire is very defensive, so attempted to fast-track %s, got result %d",
                        def_tech, res)
        if False:  # with current stats of Conc Camps, disabling this fast-track
            research_queue_list = get_research_queue_techs()
            if "CON_CONC_CAMP" in research_queue_list and aistate.character.may_research_tech_classic(
                    "CON_CONC_CAMP"):
                insert_idx = min(40,
                                 research_queue_list.index("CON_CONC_CAMP"))
            else:
                insert_idx = max(0, min(40, len(research_queue_list) - 10))
            if "SHP_DEFLECTOR_SHIELD" in research_queue_list and aistate.character.may_research_tech_classic(
                    "SHP_DEFLECTOR_SHIELD"):
                insert_idx = min(
                    insert_idx,
                    research_queue_list.index("SHP_DEFLECTOR_SHIELD"))
            for cc_tech in ["CON_ARCH_PSYCH", "CON_CONC_CAMP"]:
                if (cc_tech not in research_queue_list[:insert_idx + 1]
                        and not tech_is_complete(cc_tech) and
                        aistate.character.may_research_tech_classic(cc_tech)):
                    res = fo.issueEnqueueTechOrder(cc_tech, insert_idx)
                    debug(
                        "Empire is very aggressive, so attempted to fast-track %s, got result %d",
                        cc_tech, res)

    elif fo.currentTurn() > 100:
        generate_default_research_order()

    research_queue_list = get_research_queue_techs()
    num_techs_accelerated = 1  # will ensure leading tech doesn't get dislodged
    got_ggg_tech = tech_is_complete("PRO_ORBITAL_GEN")
    got_sym_bio = tech_is_complete("GRO_SYMBIOTIC_BIO")
    got_xeno_gen = tech_is_complete("GRO_XENO_GENETICS")
    #
    # Consider accelerating techs; priority is
    # Supply/Detect range
    # xeno arch
    # ast / GG
    # gro xeno gen
    # distrib thought
    # quant net
    # pro sing gen
    # death ray 1 cleanup

    nest_tech = Dep.NEST_DOMESTICATION_TECH
    artif_minds = Dep.LRN_ARTIF_MINDS_1

    if have_nest() and not tech_is_complete(nest_tech):
        if artif_minds in research_queue_list:
            insert_idx = 1 + research_queue_list.index(artif_minds)
        else:
            insert_idx = 1
        res = fo.issueEnqueueTechOrder(nest_tech, insert_idx)
        num_techs_accelerated += 1
        debug(
            "Have a monster nest, so attempted to fast-track %s, got result %d",
            nest_tech, res)
        research_queue_list = get_research_queue_techs()

    #
    # Supply range and detection range
    if False:  # disabled for now, otherwise just to help with cold-folding / organization
        if len(aistate.colonisablePlanetIDs) == 0:
            best_colony_site_score = 0
        else:
            best_colony_site_score = next(
                iter(aistate.colonisablePlanetIDs.items()))[1]
        if len(aistate.colonisableOutpostIDs) == 0:
            best_outpost_site_score = 0
        else:
            best_outpost_site_score = next(
                iter(aistate.colonisableOutpostIDs.items()))[1]
        need_improved_scouting = best_colony_site_score < 150 or best_outpost_site_score < 200

        if need_improved_scouting:
            if not tech_is_complete("CON_ORBITAL_CON"):
                num_techs_accelerated += 1
                if ("CON_ORBITAL_CON"
                        not in research_queue_list[:1 + num_techs_accelerated]
                    ) and (tech_is_complete("PRO_FUSION_GEN") or
                           ("PRO_FUSION_GEN"
                            in research_queue_list[:1 +
                                                   num_techs_accelerated])):
                    res = fo.issueEnqueueTechOrder("CON_ORBITAL_CON",
                                                   num_techs_accelerated)
                    debug(
                        "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d",
                        "CON_ORBITAL_CON",
                        res,
                    )
            elif not tech_is_complete("CON_CONTGRAV_ARCH"):
                num_techs_accelerated += 1
                if ("CON_CONTGRAV_ARCH"
                        not in research_queue_list[:1 + num_techs_accelerated]
                    ) and (tech_is_complete("CON_METRO_INFRA")):
                    for supply_tech in [
                            _s_tech for _s_tech in
                        ["CON_ARCH_MONOFILS", "CON_CONTGRAV_ARCH"]
                            if not tech_is_complete(_s_tech)
                    ]:
                        res = fo.issueEnqueueTechOrder(supply_tech,
                                                       num_techs_accelerated)
                        debug(
                            "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d",
                            supply_tech,
                            res,
                        )
            else:
                pass
            research_queue_list = get_research_queue_techs()
            # could add more supply tech

            if False and not tech_is_complete(
                    "SPY_DETECT_2"):  # disabled for now, detect2
                num_techs_accelerated += 1
                if "SPY_DETECT_2" not in research_queue_list[:2 +
                                                             num_techs_accelerated] and tech_is_complete(
                                                                 "PRO_FUSION_GEN"
                                                             ):
                    if "CON_ORBITAL_CON" not in research_queue_list[:1 +
                                                                    num_techs_accelerated]:
                        res = fo.issueEnqueueTechOrder("SPY_DETECT_2",
                                                       num_techs_accelerated)
                    else:
                        co_idx = research_queue_list.index("CON_ORBITAL_CON")
                        res = fo.issueEnqueueTechOrder("SPY_DETECT_2",
                                                       co_idx + 1)
                    debug(
                        "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d"
                        "CON_ORBITAL_CON",
                        res,
                    )
                research_queue_list = get_research_queue_techs()

    #
    # check to accelerate xeno_arch
    if True:  # just to help with cold-folding /  organization
        if (have_ruins() and not tech_is_complete("LRN_XENOARCH") and
                aistate.character.may_research_tech_classic("LRN_XENOARCH")):
            if artif_minds in research_queue_list:
                insert_idx = 7 + research_queue_list.index(artif_minds)
            elif "GRO_SYMBIOTIC_BIO" in research_queue_list:
                insert_idx = research_queue_list.index("GRO_SYMBIOTIC_BIO") + 1
            else:
                insert_idx = num_techs_accelerated
            if "LRN_XENOARCH" not in research_queue_list[:insert_idx]:
                for xenoTech in [
                        "LRN_XENOARCH", "LRN_TRANSLING_THT", "LRN_PHYS_BRAIN",
                        "LRN_ALGO_ELEGANCE"
                ]:
                    if not tech_is_complete(
                            xenoTech
                    ) and xenoTech not in research_queue_list[:(insert_idx +
                                                                4)]:
                        res = fo.issueEnqueueTechOrder(xenoTech, insert_idx)
                        num_techs_accelerated += 1
                        debug(
                            "ANCIENT_RUINS: have an ancient ruins, so attempted to fast-track %s to enable LRN_XENOARCH, got result %d",
                            xenoTech,
                            res,
                        )
                research_queue_list = get_research_queue_techs()

    if False and not enemies_sighted:  # curently disabled
        # params = [ (tech, gate, target_slot, add_tech_list), ]
        params = [
            ("GRO_XENO_GENETICS", "PRO_EXOBOTS", "PRO_EXOBOTS",
             ["GRO_GENETIC_MED", "GRO_XENO_GENETICS"]),
            ("PRO_EXOBOTS", "PRO_ADAPTIVE_AUTOMATION",
             "PRO_ADAPTIVE_AUTOMATION", ["PRO_EXOBOTS"]),
            ("PRO_ADAPTIVE_AUTOMATION", "PRO_NANOTECH_PROD",
             "PRO_NANOTECH_PROD", ["PRO_ADAPTIVE_AUTOMATION"]),
            (
                "PRO_INDUSTRY_CENTER_I",
                "GRO_SYMBIOTIC_BIO",
                "GRO_SYMBIOTIC_BIO",
                [
                    "PRO_ROBOTIC_PROD", "PRO_FUSION_GEN",
                    "PRO_INDUSTRY_CENTER_I"
                ],
            ),
            ("GRO_SYMBIOTIC_BIO", "SHP_ORG_HULL", "SHP_ZORTRIUM_PLATE",
             ["GRO_SYMBIOTIC_BIO"]),
        ]
        for (tech, gate, target_slot, add_tech_list) in params:
            if tech_is_complete(tech):
                break
            if tech_turns_left.get(gate, 0) not in [
                    0,
                    1,
                    2,
            ]:  # needs to exclude -1, the flag for no predicted completion
                continue
            if target_slot in research_queue_list:
                target_index = 1 + research_queue_list.index(target_slot)
            else:
                target_index = num_techs_accelerated
            for move_tech in add_tech_list:
                debug(
                    "for tech %s, target_slot %s, target_index:%s ; num_techs_accelerated:%s",
                    move_tech,
                    target_slot,
                    target_index,
                    num_techs_accelerated,
                )
                if tech_is_complete(move_tech):
                    continue
                if target_index <= num_techs_accelerated:
                    num_techs_accelerated += 1
                if move_tech not in research_queue_list[:1 + target_index]:
                    fo.issueEnqueueTechOrder(move_tech, target_index)
                    debug(
                        "Research: To prioritize %s, have advanced %s to slot %d",
                        tech, move_tech, target_index)
                    target_index += 1
    #
    # check to accelerate asteroid or GG tech
    if True:  # just to help with cold-folding / organization
        if have_asteroids():
            insert_idx = (num_techs_accelerated
                          if "GRO_SYMBIOTIC_BIO" not in research_queue_list
                          else research_queue_list.index("GRO_SYMBIOTIC_BIO"))
            ast_tech = "PRO_MICROGRAV_MAN"
            if not (tech_is_complete(ast_tech)
                    or ast_tech in research_queue_list[:(1 + insert_idx)]):
                res = fo.issueEnqueueTechOrder(ast_tech, insert_idx)
                num_techs_accelerated += 1
                debug(
                    "Asteroids: plan to colonize an asteroid belt, so attempted to fast-track %s , got result %d",
                    ast_tech,
                    res,
                )
                research_queue_list = get_research_queue_techs()
            elif tech_is_complete("SHP_ZORTRIUM_PLATE"):
                insert_idx = (
                    (1 + insert_idx)
                    if "LRN_FORCE_FIELD" not in research_queue_list else max(
                        1 + insert_idx,
                        research_queue_list.index("LRN_FORCE_FIELD") - 1))
                for ast_tech in [
                        "SHP_ASTEROID_HULLS", "SHP_IMPROVED_ENGINE_COUPLINGS"
                ]:
                    if not tech_is_complete(
                            ast_tech
                    ) and ast_tech not in research_queue_list[:insert_idx + 1]:
                        res = fo.issueEnqueueTechOrder(ast_tech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        debug(
                            "Asteroids: plan to colonize an asteroid belt, so attempted to fast-track %s , got result %d",
                            ast_tech,
                            res,
                        )
                research_queue_list = get_research_queue_techs()
        if have_gas_giant() and not tech_is_complete("PRO_ORBITAL_GEN"):
            fusion_idx = (0 if "PRO_FUSION_GEN" not in research_queue_list else
                          (1 + research_queue_list.index("PRO_FUSION_GEN")))
            forcefields_idx = (0 if "LRN_FORCE_FIELD"
                               not in research_queue_list else
                               (1 +
                                research_queue_list.index("LRN_FORCE_FIELD")))
            insert_idx = max(
                fusion_idx, forcefields_idx) if enemies_sighted else fusion_idx
            if "PRO_ORBITAL_GEN" not in research_queue_list[:insert_idx + 1]:
                res = fo.issueEnqueueTechOrder("PRO_ORBITAL_GEN", insert_idx)
                num_techs_accelerated += 1
                debug(
                    "GasGiant: plan to colonize a gas giant, so attempted to fast-track %s, got result %d",
                    "PRO_ORBITAL_GEN",
                    res,
                )
                research_queue_list = get_research_queue_techs()
    #
    # assess if our empire has any non-lousy colonizers, & boost gro_xeno_gen if we don't
    if True:  # just to help with cold-folding / organization
        if got_ggg_tech and got_sym_bio and (not got_xeno_gen):
            most_adequate = 0
            for specName in get_colony_builders():
                environs = {}
                this_spec = fo.getSpecies(specName)
                if not this_spec:
                    continue
                for ptype in [
                        fo.planetType.swamp,
                        fo.planetType.radiated,
                        fo.planetType.toxic,
                        fo.planetType.inferno,
                        fo.planetType.barren,
                        fo.planetType.tundra,
                        fo.planetType.desert,
                        fo.planetType.terran,
                        fo.planetType.ocean,
                        fo.planetType.asteroids,
                ]:
                    environ = this_spec.getPlanetEnvironment(ptype)
                    environs.setdefault(environ, []).append(ptype)
                most_adequate = max(
                    most_adequate,
                    len(environs.get(fo.planetEnvironment.adequate, [])))
            if most_adequate == 0:
                insert_idx = num_techs_accelerated
                for xg_tech in ["GRO_XENO_GENETICS", "GRO_GENETIC_ENG"]:
                    if (xg_tech
                            not in research_queue_list[:1 +
                                                       num_techs_accelerated]
                            and not tech_is_complete(xg_tech)
                            and aistate.character.may_research_tech_classic(
                                xg_tech)):
                        res = fo.issueEnqueueTechOrder(xg_tech, insert_idx)
                        num_techs_accelerated += 1
                        debug(
                            "Empire has poor colonizers, so attempted to fast-track %s, got result %d",
                            xg_tech,
                            res,
                        )
                research_queue_list = get_research_queue_techs()
    #
    # check to accelerate translinguistics
    if True:  # just to help with cold-folding / organization
        # planet is needed to determine the cost. Without a capital we have bigger problems anyway...
        if not tech_is_complete("LRN_TRANSLING_THT") and translators_wanted():
            insert_idx = num_techs_accelerated
            for dt_ech in [
                    "LRN_TRANSLING_THT", "LRN_PHYS_BRAIN", "LRN_ALGO_ELEGANCE"
            ]:
                if (dt_ech not in research_queue_list[:insert_idx + 2]
                        and not tech_is_complete(dt_ech) and
                        aistate.character.may_research_tech_classic(dt_ech)):
                    res = fo.issueEnqueueTechOrder(dt_ech, insert_idx)
                    num_techs_accelerated += 1
                    insert_idx += 1
                    fmt_str = "Empire wants to build translators, so attempted to fast-track %s (got result %d)"
                    fmt_str += " with current target_RP %.1f and current pop %.1f, on turn %d"
                    debug(fmt_str, dt_ech, res, resource_production,
                          empire.population(), fo.currentTurn())
            research_queue_list = get_research_queue_techs()
    #
    # check to accelerate distrib thought
    if True:  # just to help with cold-folding / organization
        if not tech_is_complete("LRN_DISTRIB_THOUGHT"):
            got_telepathy = False
            for specName in get_empire_planets_by_species():
                this_spec = fo.getSpecies(specName)
                if this_spec and ("TELEPATHIC" in list(this_spec.tags)):
                    got_telepathy = True
                    break
            pop_threshold = 100 if got_telepathy else 300
            if empire.population() > pop_threshold:
                insert_idx = num_techs_accelerated
                for dt_ech in [
                        "LRN_PHYS_BRAIN", "LRN_TRANSLING_THT", "LRN_PSIONICS",
                        "LRN_DISTRIB_THOUGHT"
                ]:
                    if (dt_ech not in research_queue_list[:insert_idx + 2]
                            and not tech_is_complete(dt_ech)
                            and aistate.character.may_research_tech_classic(
                                dt_ech)):
                        res = fo.issueEnqueueTechOrder(dt_ech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        fmt_str = "Empire has a telepathic race, so attempted to fast-track %s (got result %d)"
                        fmt_str += " with current target_RP %.1f and current pop %.1f, on turn %d"
                        debug(fmt_str, dt_ech, res, resource_production,
                              empire.population(), fo.currentTurn())
                research_queue_list = get_research_queue_techs()
    #
    # check to accelerate quant net
    if False:  # disabled for now, otherwise just to help with cold-folding / organization
        if aistate.character.may_research_tech_classic("LRN_QUANT_NET") and (
                population_with_research_focus() >= 40):
            if not tech_is_complete("LRN_QUANT_NET"):
                insert_idx = num_techs_accelerated  # TODO determine min target slot if reenabling
                for qnTech in ["LRN_NDIM_SUBSPACE", "LRN_QUANT_NET"]:
                    if qnTech not in research_queue_list[:insert_idx +
                                                         2] and not tech_is_complete(
                                                             qnTech):
                        res = fo.issueEnqueueTechOrder(qnTech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        debug(
                            "Empire has many researchers, so attempted to fast-track %s (got result %d) on turn %d",
                            qnTech,
                            res,
                            fo.currentTurn(),
                        )
                research_queue_list = get_research_queue_techs()

    #
    # if we own a blackhole, accelerate sing_gen and conc camp
    if True:  # just to help with cold-folding / organization
        if (fo.currentTurn() > 50 and
                len(AIstate.empireStars.get(fo.starType.blackHole, [])) != 0
                and
                aistate.character.may_research_tech_classic("PRO_SINGULAR_GEN")
                and not tech_is_complete(Dep.PRO_SINGULAR_GEN)
                and tech_is_complete("LRN_EVERYTHING")):
            # sing_tech_list = [ "LRN_GRAVITONICS" , "PRO_SINGULAR_GEN"]  # formerly also "CON_ARCH_PSYCH", "CON_CONC_CAMP",
            sing_gen_tech = fo.getTech(Dep.PRO_SINGULAR_GEN)
            sing_tech_list = [
                pre_req
                for pre_req in sing_gen_tech.recursivePrerequisites(empire_id)
                if not tech_is_complete(pre_req)
            ]
            sing_tech_list += [Dep.PRO_SINGULAR_GEN]
            for singTech in sing_tech_list:
                if singTech not in research_queue_list[:num_techs_accelerated +
                                                       1]:
                    res = fo.issueEnqueueTechOrder(singTech,
                                                   num_techs_accelerated)
                    num_techs_accelerated += 1
                    debug(
                        "have a black hole star outpost/colony, so attempted to fast-track %s, got result %d",
                        singTech,
                        res,
                    )
            research_queue_list = get_research_queue_techs()

    #
    # if got deathray from Ruins, remove most prereqs from queue
    if True:  # just to help with cold-folding / organization
        if tech_is_complete("SHP_WEAPON_4_1"):
            this_tech = fo.getTech("SHP_WEAPON_4_1")
            if this_tech:
                missing_prereqs = [
                    preReq
                    for preReq in this_tech.recursivePrerequisites(empire_id)
                    if preReq in research_queue_list
                ]
                if len(missing_prereqs
                       ) > 2:  # leave plasma 4 and 3 if up to them already
                    for preReq in missing_prereqs:  # sorted(missing_prereqs, reverse=True)[2:]
                        if preReq in research_queue_list:
                            fo.issueDequeueTechOrder(preReq)
                    research_queue_list = get_research_queue_techs()
                    if "SHP_WEAPON_4_2" in research_queue_list:  # (should be)
                        idx = research_queue_list.index("SHP_WEAPON_4_2")
                        fo.issueEnqueueTechOrder("SHP_WEAPON_4_2",
                                                 max(0, idx - 18))

    # TODO: Remove the following example code
    # Example/Test code for the new ShipDesigner functionality
    techs = [
        "SHP_WEAPON_4_2", "SHP_TRANSSPACE_DRIVE", "SHP_INTSTEL_LOG",
        "SHP_ASTEROID_HULLS", ""
    ]
    for tech in techs:
        this_tech = fo.getTech(tech)
        if not this_tech:
            debug("Invalid Tech specified")
            continue
        unlocked_items = this_tech.unlockedItems
        unlocked_hulls = []
        unlocked_parts = []
        for item in unlocked_items:
            if item.type == fo.unlockableItemType.shipPart:
                debug("Tech %s unlocks a ShipPart: %s", tech, item.name)
                unlocked_parts.append(item.name)
            elif item.type == fo.unlockableItemType.shipHull:
                debug("Tech %s unlocks a ShipHull: %s", tech, item.name)
                unlocked_hulls.append(item.name)
        if not (unlocked_parts or unlocked_hulls):
            debug("No new ship parts/hulls unlocked by tech %s", tech)
            continue
        old_designs = ShipDesignAI.WarShipDesigner().optimize_design(
            consider_fleet_count=False)
        new_designs = ShipDesignAI.WarShipDesigner().optimize_design(
            additional_hulls=unlocked_hulls,
            additional_parts=unlocked_parts,
            consider_fleet_count=False)
        if not (old_designs and new_designs):
            # AI is likely defeated; don't bother with logging error message
            continue
        old_rating, old_pid, old_design_id, old_cost, old_stats = old_designs[
            0]
        old_design = fo.getShipDesign(old_design_id)
        new_rating, new_pid, new_design_id, new_cost, new_stats = new_designs[
            0]
        new_design = fo.getShipDesign(new_design_id)
        if new_rating > old_rating:
            debug("Tech %s gives access to a better design!", tech)
            debug("old best design: Rating %.5f", old_rating)
            debug("old design specs: %s - %s", old_design.hull,
                  list(old_design.parts))
            debug("new best design: Rating %.5f", new_rating)
            debug("new design specs: %s - %s", new_design.hull,
                  list(new_design.parts))
        else:
            debug(
                "Tech %s gives access to new parts or hulls but there seems to be no military advantage.",
                tech)
示例#30
0
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire,  secureAIFleetMissions,  verbose=True):
    "return the invasion value (score, troops) of a planet"
    detail = []
    buildingValues = {"BLD_IMPERIAL_PALACE":                    1000,
                                            "BLD_CULTURE_ARCHIVES":                 1000,
                                            "BLD_SHIPYARD_BASE":                        100,
                                            "BLD_SHIPYARD_ORG_ORB_INC":     200,
                                            "BLD_SHIPYARD_ORG_XENO_FAC": 200,
                                            "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200,
                                            "BLD_SHIPYARD_CON_NANOROBO": 300,
                                            "BLD_SHIPYARD_CON_GEOINT":      400,
                                            "BLD_SHIPYARD_CON_ADV_ENGINE": 1000,
                                            "BLD_SHIPYARD_AST":                             300,
                                            "BLD_SHIPYARD_AST_REF":                     1000,
                                            "BLD_SHIPYARD_ENRG_SOLAR":          1500,
                                            "BLD_INDUSTRY_CENTER":                   500,
                                            "BLD_GAS_GIANT_GEN":                           200,
                                            "BLD_SOL_ORB_GEN":                              800,
                                            "BLD_BLACK_HOLE_POW_GEN":       2000,
                                            "BLD_ENCLAVE_VOID":                             500,
                                            "BLD_NEUTRONIUM_EXTRACTOR": 2000,
                                            "BLD_NEUTRONIUM_SYNTH":             2000,
                                            "BLD_NEUTRONIUM_FORGE":             1000,
                                            "BLD_CONC_CAMP":                                    100,
                                            "BLD_BIOTERROR_PROJECTOR":      1000,
                                            "BLD_SHIPYARD_ENRG_COMP":         3000,
                                            }
    #TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empireID = empire.empireID
    maxJumps=8
    planet = universe.getPlanet(planetID)
    if (planet == None) :  #TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't access any info for planet id %d"%planetID
        return [0, 0]

    sysPartialVisTurn = dictFromMap(universe.getVisibilityTurnsMap(planet.systemID,  empireID)).get(fo.visibility.partial, -9999)
    planetPartialVisTurn = dictFromMap(universe.getVisibilityTurnsMap(planetID,  empireID)).get(fo.visibility.partial, -9999)

    if planetPartialVisTurn < sysPartialVisTurn:
        print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)"%planetID
        return [0, 0]  #last time we had partial vis of the system, the planet was stealthed to us #TODO: track detection strength, order new scouting when it goes up

    specName=planet.speciesName
    species=fo.getSpecies(specName)
    if not species: #this call iterates over this Empire's available species with which it could colonize after an invasion
        planetEval = ColonisationAI.assignColonisationValues([planetID],  EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION,  [planetID],  None,  empire, detail) #evaluatePlanet is imported from ColonisationAI
        popVal = max( 0.75*planetEval.get(planetID,  [0])[0],   ColonisationAI.evaluatePlanet(planetID,  EnumsAI.AIFleetMissionType.FLEET_MISSION_OUTPOST,  [planetID],  None,  empire, detail)  )
    else:
        popVal = ColonisationAI.evaluatePlanet(planetID,  EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION,  [planetID],  specName,  empire, detail) #evaluatePlanet is imported from ColonisationAI

    bldTally=0
    for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]:
        bval = buildingValues.get(bldType,  50)
        bldTally += bval
        detail.append("%s: %d"%(bldType,  bval))

    pSysID = planet.systemID
    capitolID = PlanetUtilsAI.getCapital()
    leastJumpsPath = []
    clear_path = True
    if capitolID:
        homeworld = universe.getPlanet(capitolID)
        if homeworld:
            homeSystemID = homeworld.systemID
            evalSystemID = planet.systemID
            if (homeSystemID != -1) and (evalSystemID != -1):
                leastJumpsPath = list(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID))
                maxJumps =  len(leastJumpsPath)
    system_status = foAI.foAIstate.systemStatus.get(pSysID, {})
    sysFThrt = system_status.get('fleetThreat', 1000 )
    sysMThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('monsterThreat', 0 )
    sysPThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('planetThreat', 0 )
    sysTotThrt = sysFThrt + sysMThrt + sysPThrt
    max_path_threat = sysFThrt
    mil_ship_rating = ProductionAI.curBestMilShipRating()
    for path_sys_id in leastJumpsPath:
        path_leg_status = foAI.foAIstate.systemStatus.get(path_sys_id,  {})
        path_leg_threat = path_leg_status.get('fleetThreat', 1000 ) + path_leg_status.get('monsterThreat', 0 )
        if  path_leg_threat > 0.5 * mil_ship_rating:
            clear_path = False
            if path_leg_threat > max_path_threat:
                max_path_threat = path_leg_threat

    troops = planet.currentMeterValue(fo.meterType.troops)
    maxTroops = planet.currentMeterValue(fo.meterType.maxTroops)

    this_system = universe.getSystem(pSysID)
    secure_targets = [pSysID] + list(this_system.planetIDs)
    system_secured = False
    for mission in secureAIFleetMissions:
        if system_secured:
            break
        secure_fleet_id = mission.target_id
        s_fleet = universe.getFleet(secure_fleet_id)
        if (not s_fleet) or (s_fleet.systemID != pSysID):
            continue
        for ai_target in mission.getAITargets(EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE):
            target_obj = ai_target.target_obj
            if (target_obj is not None) and target_obj.id in secure_targets:
                system_secured = True
                break

    pmaxShield = planet.currentMeterValue(fo.meterType.maxShield)
    if verbose:
        print "invasion eval of %s  %d --- maxShields %.1f -- sysFleetThreat %.1f  -- sysMonsterThreat %.1f"%(planet.name,  planetID,  pmaxShield,  sysFThrt,  sysMThrt)
    supplyVal=0
    enemyVal=0
    if planet.owner!=-1 : #value in taking this away from an enemy
        enemyVal= 20* (planet.currentMeterValue(fo.meterType.targetIndustry) +  2*planet.currentMeterValue(fo.meterType.targetResearch))
    if pSysID  in ColonisationAI.annexableSystemIDs: #TODO: extend to rings
        supplyVal =  100
    elif pSysID in ColonisationAI.annexableRing1:
        supplyVal =  200
    elif pSysID in ColonisationAI.annexableRing2:
        supplyVal =  300
    elif pSysID in ColonisationAI.annexableRing2:
        supplyVal =  400
    if ( max_path_threat > 0.5 * mil_ship_rating ):
        if ( max_path_threat < 3 * mil_ship_rating ):
            supplyVal *= 0.5
        else:
            supplyVal *= 0.2
        
    threatFactor = min(1,  0.2*MilitaryAI.totMilRating/(sysTotThrt+0.001))**2  #devalue invasions that would require too much military force
    buildTime=4
    if system_secured:
        plannedTroops = troops
    else:
        plannedTroops = min(troops+maxJumps+buildTime,  maxTroops)
    if ( empire.getTechStatus("SHP_ORG_HULL") != fo.techStatus.complete ):
        troopCost = math.ceil( plannedTroops/6.0) *  ( 40*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) )
    else:
        troopCost = math.ceil( plannedTroops/6.0) *  ( 20*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) )
    planet_score = threatFactor*max(0,  popVal+supplyVal+bldTally+enemyVal-0.8*troopCost)
    if clear_path:
        planet_score *= 1.5
    invscore =  [ planet_score,  plannedTroops ]
    print invscore, "projected Troop Cost:",  troopCost,  ", threatFactor: ", threatFactor,  ", planet detail ",   detail, "popval,  supplyval,  bldval,  enemyval",   popVal,  supplyVal,  bldTally,  enemyVal
    return   invscore
示例#31
0
def colony_detectable_by_empire(planet_id, species_name=None, empire=ALL_EMPIRES, future_stealth_bonus=0,
                                default_result=True):
    """
    Predicts if a planet/colony is/will-be detectable by an empire.

    The passed empire value can be a single empire ID or a list of empire IDs.  If passed ALL_empires, will use the list
    of all empires.  When using a list of empires (or when passed ALL_EMPIRES), the present empire is excluded.  To
    check for the present empire the current empire ID must be passed as a simple int.  Ignores current ownership of the
    planet unless the passed empire value is a simple int matching fo.empireID(), because in most cases we are concerned
    about (i) visibility to us of a planet we do not own, or (ii) visibility by enemies of a planet we own or expect to
    own at the time we are making the visibility projection for (even if they may own it right now).  The only case
    where current ownership matters is when we are considering whether to abort a colonization mission, which might be
    for a planet we already own.

    :param planet_id: required, the planet of concern
    :type planet_id: int
    :param species_name: will override the existing planet species if provided
    :type species_name: str
    :param empire: empire ID (or list of empire IDs) whose detection ability is of concern
    :type empire: int | list[int]
    :param future_stealth_bonus: can specify a projected future stealth bonus, such as from a stealth tech
    :type future_stealth_bonus: int
    :param default_result: generally for offensive assessments should be False, for defensive should be True
    :type default_result: bool
    :return: whether the planet is predicted to be detectable
    :rtype: bool
    """
    # The future_stealth_bonus can be used if the AI knows it has researched techs that would grant a stealth bonus to
    # the planet once it was colonized/captured

    planet = fo.getUniverse().getPlanet(planet_id)
    if not planet:
        error("Couldn't retrieve planet ID %d." % planet_id)
        return default_result
    if species_name is None:
        species_name = planet.speciesName

    # in case we are checking about aborting a colonization mission
    if empire == fo.empireID() and planet.ownedBy(empire):
        return True

    species = fo.getSpecies(species_name)
    if species:
        species_tags = species.tags
    elif species_name == "":
        species_tags = []
    else:
        error("Couldn't retrieve species named '%s'." % species_name)
        return default_result

    # could just check stealth meter, but this approach might allow us to plan ahead a bit even if the planet
    # is temporarily stealth boosted by temporary effects like ion storm
    planet_stealth = max([AIDependencies.BASE_PLANET_STEALTH] +
                         [AIDependencies.STEALTH_SPECIAL_STRENGTHS.get(_spec, 0) for _spec in planet.specials])
    # TODO: check planet buildings for stealth bonuses

    # if the planet already has an existing stealth special, then the most common situation is that it would be
    # overlapping with or superseded by the future_stealth_bonus, not additive with it.
    planet_stealth = max(planet_stealth, AIDependencies.BASE_PLANET_STEALTH + future_stealth_bonus)

    total_stealth = planet_stealth + sum([AIDependencies.STEALTH_STRENGTHS_BY_SPECIES_TAG.get(tag, 0)
                                          for tag in species_tags])
    if isinstance(empire, int):
        empire_detection = get_empire_detection(empire)
    else:
        empire_detection = get_max_empire_detection(empire)
    return total_stealth < empire_detection
示例#32
0
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire):
    "return the invasion value of a planet"
    detail = []
    buildingValues = {"BLD_IMPERIAL_PALACE":                    1000, 
                                            "BLD_CULTURE_ARCHIVES":                 1000, 
                                            "BLD_SHIPYARD_BASE":                        100, 
                                            "BLD_SHIPYARD_ORG_ORB_INC":     200, 
                                            "BLD_SHIPYARD_ORG_XENO_FAC": 200, 
                                            "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200, 
                                            "BLD_SHIPYARD_CON_NANOROBO": 300, 
                                            "BLD_SHIPYARD_CON_GEOINT":      400, 
                                            "BLD_SHIPYARD_CON_ADV_ENGINE": 1000, 
                                            "BLD_SHIPYARD_AST":                             150, 
                                            "BLD_SHIPYARD_AST_REF":                     500, 
                                            "BLD_SHIPYARD_ENRG_COMP":           500, 
                                            "BLD_SHIPYARD_ENRG_SOLAR":          1500, 
                                            "BLD_INDUSTRY_CENTER":                   500, 
                                            "BLD_GAS_GIANT_GEN":                           200, 
                                            "BLD_SOL_ORB_GEN":                              800, 
                                            "BLD_BLACK_HOLE_POW_GEN":       2000, 
                                            "BLD_ENCLAVE_VOID":                             500, 
                                            "BLD_NEUTRONIUM_EXTRACTOR": 2000, 
                                            "BLD_NEUTRONIUM_SYNTH":             2000, 
                                            "BLD_NEUTRONIUM_FORGE":             1000, 
                                            "BLD_CONC_CAMP":                                    100, 
                                            "BLD_BIOTERROR_PROJECTOR":      1000, 
                                            "BLD_SHIPYARD_ENRG_COMP":         3000, 
                                            }
    #TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empireID = empire.empireID
    maxJumps=8
    planet = universe.getPlanet(planetID)
    if (planet == None) :  #TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't get current info on planet %d"%planetID
        return 0, 0

    specName=planet.speciesName
    species=fo.getSpecies(specName)
    if not species:#TODO:  probably stealth makes planet inacccesible & should abort
        return 0, 0
    else:
        popVal = ColonisationAI.evaluatePlanet(planetID,  EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION,  [planetID],  species,  empire, detail) #evaluatePlanet is imported from ColonisationAI

    bldTally=0
    for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]:
        bval = buildingValues.get(bldType,  50)
        bldTally += bval
        detail.append("%s: %d"%(bldType,  bval))
        
        capitolID = PlanetUtilsAI.getCapital()
        if capitolID:
            homeworld = universe.getPlanet(capitolID)
            if homeworld:
                homeSystemID = homeworld.systemID
                evalSystemID = planet.systemID
                leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID))
            maxJumps =  leastJumpsPath
        
    troops = planet.currentMeterValue(fo.meterType.troops)
    maxTroops = planet.currentMeterValue(fo.meterType.maxTroops)
    
    popTSize = planet.currentMeterValue(fo.meterType.targetPopulation)#TODO: adjust for empire tech
    planetSpecials = list(planet.specials)
    pSysID = planet.systemID#TODO: check star value
    
    pmaxShield = planet.currentMeterValue(fo.meterType.maxShield)
    sysFThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('fleetThreat', 1000 )
    sysMThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('monsterThreat', 0 )
    print "invasion eval of %s  %d --- maxShields %.1f -- sysFleetThreat %.1f  -- sysMonsterThreat %.1f"%(planet.name,  planetID,  pmaxShield,  sysFThrt,  sysMThrt)
    supplyVal=0
    enemyVal=0
    if planet.owner!=-1 : #value in taking this away from an enemy
        enemyVal= 20* (planet.currentMeterValue(fo.meterType.targetIndustry) +  2*planet.currentMeterValue(fo.meterType.targetResearch))
    if planetID  in fleetSupplyablePlanetIDs: #TODO: extend to rings
        supplyVal =  100
        if planet.owner== -1:
        #if  (pmaxShield <10):
            if ( sysFThrt < 0.5*ProductionAI.curBestMilShipRating() ):
               if ( sysMThrt < 3*ProductionAI.curBestMilShipRating()):
                    supplyVal = 50
               else:
                    supplyVal = 20
            else:
                supplyVal *= int( min(1, ProductionAI.curBestMilShipRating() /  sysFThrt )  )
    buildTime=4
    plannedTroops = min(troops+maxJumps+buildTime,  maxTroops)
    if ( empire.getTechStatus("SHP_ORG_HULL") != fo.techStatus.complete ):
        troopCost = math.ceil( plannedTroops/6.0) *  ( 40*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) )
    else:
        troopCost = math.ceil( plannedTroops/6.0) *  ( 20*( 1+foAI.foAIstate.shipCount * AIDependencies.shipUpkeep ) )
    invscore =  max(0,  popVal+supplyVal+bldTally+enemyVal-0.8*troopCost),  plannedTroops
    print invscore, "projected Troop Cost:",  troopCost,  "planet detail ",   detail,  popVal,  supplyVal,  bldTally,  enemyVal
    return   invscore
示例#33
0
def evaluate_invasion_planet(planet_id, empire, secure_fleet_missions, verbose=True):
    """Return the invasion value (score, troops) of a planet."""
    detail = []
    building_values = {"BLD_IMPERIAL_PALACE": 1000,
                       "BLD_CULTURE_ARCHIVES": 1000,
                       "BLD_SHIPYARD_BASE": 100,
                       "BLD_SHIPYARD_ORG_ORB_INC": 200,
                       "BLD_SHIPYARD_ORG_XENO_FAC": 200,
                       "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200,
                       "BLD_SHIPYARD_CON_NANOROBO": 300,
                       "BLD_SHIPYARD_CON_GEOINT": 400,
                       "BLD_SHIPYARD_CON_ADV_ENGINE": 1000,
                       "BLD_SHIPYARD_AST": 300,
                       "BLD_SHIPYARD_AST_REF": 1000,
                       "BLD_SHIPYARD_ENRG_SOLAR": 1500,
                       "BLD_INDUSTRY_CENTER": 500,
                       "BLD_GAS_GIANT_GEN": 200,
                       "BLD_SOL_ORB_GEN": 800,
                       "BLD_BLACK_HOLE_POW_GEN": 2000,
                       "BLD_ENCLAVE_VOID": 500,
                       "BLD_NEUTRONIUM_EXTRACTOR": 2000,
                       "BLD_NEUTRONIUM_SYNTH": 2000,
                       "BLD_NEUTRONIUM_FORGE": 1000,
                       "BLD_CONC_CAMP": 100,
                       "BLD_BIOTERROR_PROJECTOR": 1000,
                       "BLD_SHIPYARD_ENRG_COMP": 3000,
                       }
    # TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empire_id = empire.empireID
    max_jumps = 8
    planet = universe.getPlanet(planet_id)
    if planet is None:  # TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't access any info for planet id %d" % planet_id
        return [0, 0]

    sys_partial_vis_turn = universe.getVisibilityTurnsMap(planet.systemID, empire_id).get(fo.visibility.partial, -9999)
    planet_partial_vis_turn = universe.getVisibilityTurnsMap(planet_id, empire_id).get(fo.visibility.partial, -9999)

    if planet_partial_vis_turn < sys_partial_vis_turn:
        print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id
        # TODO: track detection strength, order new scouting when it goes up
        return [0, 0]  # last time we had partial vis of the system, the planet was stealthed to us

    species_name = planet.speciesName
    species = fo.getSpecies(species_name)
    if not species:  # this call iterates over this Empire's available species with which it could colonize after an invasion
        planet_eval = ColonisationAI.assign_colonisation_values([planet_id], EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, None, empire, detail)
        pop_val = max(0.75*planet_eval.get(planet_id, [0])[0], ColonisationAI.evaluate_planet(planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_OUTPOST, None, empire, detail))
    else:
        pop_val = ColonisationAI.evaluate_planet(planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, species_name, empire, detail)

    bld_tally = 0
    for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]:
        bval = building_values.get(bldType, 50)
        bld_tally += bval
        detail.append("%s: %d" % (bldType, bval))

    p_sys_id = planet.systemID
    capitol_id = PlanetUtilsAI.get_capital()
    least_jumps_path = []
    clear_path = True
    if capitol_id:
        homeworld = universe.getPlanet(capitol_id)
        if homeworld:
            home_system_id = homeworld.systemID
            eval_system_id = planet.systemID
            if (home_system_id != -1) and (eval_system_id != -1):
                least_jumps_path = list(universe.leastJumpsPath(home_system_id, eval_system_id, empire_id))
                max_jumps = len(least_jumps_path)
    system_status = foAI.foAIstate.systemStatus.get(p_sys_id, {})
    system_fleet_treat = system_status.get('fleetThreat', 1000)
    system_monster_threat = system_status.get('monsterThreat', 0)
    sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get('planetThreat', 0)
    max_path_threat = system_fleet_treat
    mil_ship_rating = 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

    troops = planet.currentMeterValue(fo.meterType.troops)
    max_troops = planet.currentMeterValue(fo.meterType.maxTroops)

    this_system = universe.getSystem(p_sys_id)
    secure_targets = [p_sys_id] + list(this_system.planetIDs)
    system_secured = False
    for mission in secure_fleet_missions:
        if system_secured:
            break
        secure_fleet_id = mission.target_id
        s_fleet = universe.getFleet(secure_fleet_id)
        if not s_fleet or s_fleet.systemID != p_sys_id:
            continue
        for ai_target in mission.get_targets(EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE):
            target_obj = ai_target.target_obj
            if (target_obj is not None) and target_obj.id in secure_targets:
                system_secured = True
                break

    if verbose:
        print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f" % (
            planet.name, planet_id, planet.currentMeterValue(fo.meterType.maxShield), system_fleet_treat,
            system_monster_threat)
    supply_val = 0
    enemy_val = 0
    if planet.owner != -1:  # value in taking this away from an enemy
        enemy_val = 20 * (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch))
    if p_sys_id in ColonisationAI.annexable_system_ids:  # TODO: extend to rings
        supply_val = 100
    elif p_sys_id in ColonisationAI.annexable_ring1:
        supply_val = 200
    elif p_sys_id in ColonisationAI.annexable_ring2:
        supply_val = 300
    elif p_sys_id in ColonisationAI.annexable_ring3:
        supply_val = 400
    if max_path_threat > 0.5 * mil_ship_rating:
        if max_path_threat < 3 * mil_ship_rating:
            supply_val *= 0.5
        else:
            supply_val *= 0.2
        
    threat_factor = min(1, 0.2*MilitaryAI.totMilRating/(sys_total_threat+0.001))**2  # devalue invasions that would require too much military force
    build_time = 4

    planned_troops = troops if system_secured else min(troops+max_jumps+build_time, max_troops)
    if not tech_is_complete("SHP_ORG_HULL"):
        troop_cost = math.ceil(planned_troops/6.0) * (40*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP))
    else:
        troop_cost = math.ceil(planned_troops/6.0) * (20*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP))
    planet_score = retaliation_risk_factor(planet.owner) * threat_factor * max(0, pop_val+supply_val+bld_tally+enemy_val-0.8*troop_cost)
    if clear_path:
        planet_score *= 1.5
    invasion_score = [planet_score, planned_troops]
    print invasion_score, "projected Troop Cost:", troop_cost, ", threatFactor: ", threat_factor, ", planet detail ", detail, "popval, supplyval, bldval, enemyval", pop_val, supply_val, bld_tally, enemy_val
    return invasion_score
示例#34
0
def getColonyFleets():
    global empireSpecies,  empireColonizers,  empireSpeciesSystems,  annexableSystemIDs,  annexableRing1,  annexableRing2,  annexableRing3
    global  annexablePlanetIDs,  curBestMilShipRating
    
    curBestMilShipRating = ProductionAI.curBestMilShipRating()
    
    "get colony fleets"

    allColonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)
    AIstate.colonyFleetIDs[:] = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allColonyFleetIDs)

    # get suppliable systems and planets
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    capitalID = PlanetUtilsAI.getCapital()
    #capitalID = empire.capitalID
    homeworld=None
    if capitalID:
        homeworld = universe.getPlanet(capitalID)
    if homeworld:
        speciesName = homeworld.speciesName
        homeworldName=homeworld.name
        homeSystemID = homeworld.systemID
    else:
        speciesName = ""
        homeworldName=" no remaining homeworld "
        homeSystemID = -1
    if not speciesName:
        speciesName = foAI.foAIstate.origSpeciesName
    species = fo.getSpecies(speciesName)
    if not species:
        print "**************************************************************************************"
        print "**************************************************************************************"
        print "Problem determining species for colonization planning: capitalID: %s,  homeworld %s  and species name %s"%(capitalID,  homeworldName,  speciesName)
    else:
        print "Plannning colonization for species name %s"%species.name

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

    print "-------\nEmpire Obstructed Starlanes:"
    print  list(empire.obstructedStarlanes())


    annexableSystemIDs.clear()
    annexableRing1.clear()
    annexableRing2.clear()
    annexableRing3.clear()
    annexablePlanetIDs.clear()
    for sysID in empire.fleetSupplyableSystemIDs:
        annexableSystemIDs.add(sysID)
        for nID in  universe.getImmediateNeighbors(sysID,  empireID):
            annexableSystemIDs.add(nID)
            annexableRing1.add(nID)
    annexableRing1.difference_update(empire.fleetSupplyableSystemIDs)
    print "First Ring of annexable systems: ",  PlanetUtilsAI.sysNameIDs(annexableRing1)
    if empire.getTechStatus("CON_ORBITAL_CON") == fo.techStatus.complete:
        for sysID in list(annexableRing1):
            for nID in  universe.getImmediateNeighbors(sysID,  empireID):
                annexableRing2.add(nID)
        annexableRing2.difference_update(annexableSystemIDs)
        print "Second Ring of annexable systems: ",  PlanetUtilsAI.sysNameIDs(annexableRing2)
        annexableSystemIDs.update(annexableRing2)
        if foAI.foAIstate.aggression > fo.aggression.cautious:
            for sysID in list(annexableRing2):
                for nID in  universe.getImmediateNeighbors(sysID,  empireID):
                    annexableRing3.add(nID)
            annexableRing3.difference_update(annexableSystemIDs)
            print "Third Ring of annexable systems: ",  PlanetUtilsAI.sysNameIDs(annexableRing3)
            annexableSystemIDs.update(annexableRing3)
    annexablePlanetIDs.update( PlanetUtilsAI.getPlanetsInSystemsIDs(annexableSystemIDs))

    # get outpost and colonization planets
    
    exploredSystemIDs = foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_EXPLORED)
    unExSysIDs = list(foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED))
    unExSystems = map(universe.getSystem,  unExSysIDs)
    print "Unexplored Systems: %s " % [(sysID,  (sys and sys.name) or "name unknown") for sysID,  sys in zip( unExSysIDs,  unExSystems)]
    print "Explored SystemIDs: " + str(list(exploredSystemIDs))

    exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs)
    print "Explored PlanetIDs: " + str(exploredPlanetIDs)
    print ""
    
    #visibleSystemIDs = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys()
    #visiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(visibleSystemIDs)
    #print "VisiblePlanets: %s "%[ (pid,  (universe.getPlanet(pid) and  universe.getPlanet(pid).name) or "unknown") for pid in  visiblePlanetIDs]
    #print ""
    
    #accessibleSystemIDs = [sysID for sysID in visibleSystemIDs if  universe.systemsConnected(sysID, homeSystemID, empireID) ]
    #acessiblePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(accessibleSystemIDs)

    empireOwnedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    print "Empire Owned PlanetIDs:            " + str(empireOwnedPlanetIDs)
    
    #allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(exploredPlanetIDs) #working with Explored systems not all 'visible' because might not have a path to the latter
    allOwnedPlanetIDs = PlanetUtilsAI.getAllOwnedPlanetIDs(annexablePlanetIDs) #
    print "All annexable Owned or Populated PlanetIDs: " + str(set(allOwnedPlanetIDs)-set(empireOwnedPlanetIDs))

    #unOwnedPlanetIDs = list(set(exploredPlanetIDs) -set(allOwnedPlanetIDs))
    unOwnedPlanetIDs = list(set(annexablePlanetIDs) -set(allOwnedPlanetIDs))
    print "UnOwned annexable PlanetIDs:             " + str(PlanetUtilsAI.planetNameIDs(unOwnedPlanetIDs))
    
    empirePopCtrs = set( PlanetUtilsAI.getPopulatedPlanetIDs(  empireOwnedPlanetIDs) )
    empireOutpostIDs=set(empireOwnedPlanetIDs) - empirePopCtrs
    AIstate.popCtrIDs[:]=list(empirePopCtrs)
    AIstate.popCtrSystemIDs[:]=list(set(PlanetUtilsAI.getSystems(empirePopCtrs)))
    AIstate.outpostIDs[:]=list(empireOutpostIDs)
    AIstate.outpostSystemIDs[:]=list(set(PlanetUtilsAI.getSystems(empireOutpostIDs)))
    AIstate.colonizedSystems.clear()
    for pid in empireOwnedPlanetIDs:
        planet=universe.getPlanet(pid)
        if planet:
            AIstate.colonizedSystems.setdefault(planet.systemID,  []).append(pid)   # track these to plan Solar Generators and Singularity Generators
    AIstate.empireStars.clear()
    for sysID in AIstate.colonizedSystems:
        system = universe.getSystem(sysID)
        if system:
            AIstate.empireStars.setdefault(system.starType, []).append(sysID)
    
    
    oldPopCtrs=[]
    for specN in empireSpecies:
        oldPopCtrs.extend(empireSpecies[specN])
    oldEmpSpec = empireSpecies
    empireSpecies.clear()
    oldEmpCol=empireColonizers
    empireColonizers.clear()
    if empire.getTechStatus(TechsListsAI.exobotTechName) == fo.techStatus.complete:
        empireColonizers["SP_EXOBOT"]=[]# get it into colonizer list even if no colony yet
    empireSpeciesSystems.clear()
    
    for pID in empirePopCtrs:
        planet=universe.getPlanet(pID)
        if not planet:
            print "Error empire has apparently lost sight of former colony at planet %d but doesn't realize it"%pID
            continue
        pSpecName=planet.speciesName
        if pID not in oldPopCtrs:
            if  (AIFocusType.FOCUS_MINING in planet.availableFoci): 
                fo.issueChangeFocusOrder(pID, AIFocusType.FOCUS_MINING)
                print "Changing focus of newly settled planet ID %d : %s  to mining "%(pID,  planet.name )
        empireSpecies[pSpecName] = empireSpecies.get(pSpecName,  [])+[pID]
    print "\n"+"Empire species roster:"
    for specName in empireSpecies:
        thisSpec=fo.getSpecies(specName)
        if thisSpec:
            shipyards=[]
            for pID in empireSpecies[specName]:
                planet=universe.getPlanet(pID)
                if thisSpec.canColonize:
                    if "BLD_SHIPYARD_BASE" in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]:
                        shipyards.append(pID)
                empireSpeciesSystems.setdefault(planet.systemID,  {}).setdefault('pids', []).append(pID)
            if thisSpec.canColonize:
                empireColonizers[specName]=shipyards
            print "%s on planets %s; can%s colonize from %d shipyards; has tags %s"%(specName,  empireSpecies[specName],  ["not", ""][thisSpec.canColonize], len(shipyards),  list(thisSpec.tags))
        else:
            print "Unable to retrieve info for Species named %s"%specName
    print""
    if empireSpecies!=oldEmpSpec:
        print "Old empire species: %s  ; new empire species: %s"%(oldEmpSpec,  empireSpecies)
    if empireColonizers!=oldEmpCol:
        print "Old empire colonizers: %s  ; new empire colonizers: %s"%(oldEmpCol,  empireColonizers)
    
    print 

    # export colony targeted systems for other AI modules
    colonyTargetedPlanetIDs = getColonyTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION, empireID)
    allColonyTargetedSystemIDs = PlanetUtilsAI.getSystems(colonyTargetedPlanetIDs)
    AIstate.colonyTargetedSystemIDs = allColonyTargetedSystemIDs
    print ""
    print "Colony Targeted SystemIDs:         " + str(AIstate.colonyTargetedSystemIDs)
    print "Colony Targeted PlanetIDs:         " + str(colonyTargetedPlanetIDs)

    colonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)
    if not colonyFleetIDs:
        print "Available Colony Fleets:             0"
    else:
        print "Colony FleetIDs:                   " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION))

    numColonyFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(colonyFleetIDs))
    print "Colony Fleets Without Missions:      " + str(numColonyFleets)

    outpostTargetedPlanetIDs = getOutpostTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, empireID)
    allOutpostTargetedSystemIDs = PlanetUtilsAI.getSystems(outpostTargetedPlanetIDs)

    # export outpost targeted systems for other AI modules
    AIstate.outpostTargetedSystemIDs = allOutpostTargetedSystemIDs
    print ""
    print "Outpost Targeted SystemIDs:        " + str(AIstate.outpostTargetedSystemIDs)
    print "Outpost Targeted PlanetIDs:        " + str(outpostTargetedPlanetIDs)

    outpostFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST)
    if not outpostFleetIDs:
        print "Available Outpost Fleets:            0"
    else:
        print "Outpost FleetIDs:                  " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST))

    numOutpostFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(outpostFleetIDs))
    print "Outpost Fleets Without Missions:     " + str(numOutpostFleets)

    evaluatedColonyPlanetIDs = list(set(unOwnedPlanetIDs).union(empireOutpostIDs) - set(colonyTargetedPlanetIDs) )
    # print "Evaluated Colony PlanetIDs:        " + str(evaluatedColonyPlanetIDs)

    evaluatedOutpostPlanetIDs = list(set(unOwnedPlanetIDs) - set(outpostTargetedPlanetIDs)- set(colonyTargetedPlanetIDs))
    # print "Evaluated Outpost PlanetIDs:       " + str(evaluatedOutpostPlanetIDs)

    evaluatedColonyPlanets = assignColonisationValues(evaluatedColonyPlanetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION, fleetSupplyablePlanetIDs, species, empire)
    removeLowValuePlanets(evaluatedColonyPlanets)

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

    print ""
    print "Settleable Colony Planets (score,species) | ID | Name | Specials:"
    for ID, score in sortedPlanets:
        print "   %15s | %5s  | %s  | %s "%(score,  ID,  universe.getPlanet(ID).name ,  list(universe.getPlanet(ID).specials)) 
    print ""

    # export planets for other AI modules
    foAI.foAIstate.colonisablePlanetIDs = sortedPlanets#TODO: should include species designation corresponding to rating

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

    evaluatedOutpostPlanets = assignColonisationValues(evaluatedOutpostPlanetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, fleetSupplyablePlanetIDs, species, empire)
    removeLowValuePlanets(evaluatedOutpostPlanets) #bad! lol, was preventing all mining outposts

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

    print "Settleable Outpost PlanetIDs:"
    for ID, score in sortedOutposts:
        print "   %5s | %5s  | %s  | %s "%(score,  ID,  universe.getPlanet(ID).name ,  list(universe.getPlanet(ID).specials)) 
    print ""

    # export outposts for other AI modules
    foAI.foAIstate.colonisableOutpostIDs = sortedOutposts
示例#35
0
def evaluate_invasion_planet(planet_id):
    """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:
        debug("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=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 visibility 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)
    empire_research_list = tuple(element.tech
                                 for element in fo.getEmpire().researchQueue)
    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],
            calculate_planet_colonization_rating.
            calculate_planet_colonization_rating(
                planet_id=planet_id,
                mission_type=MissionType.OUTPOST,
                spec_name=None,
                detail=detail,
                empire_research_list=empire_research_list,
            ),
        )
    else:
        colony_base_value = calculate_planet_colonization_rating.calculate_planet_colonization_rating(
            planet_id=planet_id,
            mission_type=MissionType.INVASION,
            spec_name=species_name,
            detail=detail,
            empire_research_list=empire_research_list,
        )

    # 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))

    least_jumps_path, max_jumps = _get_path_from_capital(planet)
    clear_path = True

    aistate = get_aistate()
    system_status = aistate.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 = aistate.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

    secure_fleets = get_aistate().get_fleet_missions_with_any_mission_types(
        [MissionType.SECURE, MissionType.MILITARY])
    for mission in secure_fleets:
        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 in [MissionType.SECURE, MissionType.MILITARY]:
            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)
    debug(
        "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 = 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 += 0.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,
            get_species_tag_grade(species_here, Tags.ATTACKTROOPS))
        planned_troops = troops if system_secured else min(
            troops + troop_regen * (max_jumps + build_time), max_troops)
        planned_troops += 0.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.0, 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 military 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
    debug(
        " - 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,
    )
    debug(" - system secured: %s" % system_secured)
    return [planet_score, planned_troops]
示例#36
0
def colony_detectable_by_empire(planet_id,
                                species_name=None,
                                empire=ALL_EMPIRES,
                                future_stealth_bonus=0,
                                default_result=True):
    """
    Predicts if a planet/colony is/will-be detectable by an empire.

    The passed empire value can be a single empire ID or a list of empire IDs.  If passed ALL_empires, will use the list
    of all empires.  When using a list of empires (or when passed ALL_EMPIRES), the present empire is excluded.  To
    check for the present empire the current empire ID must be passed as a simple int.  Ignores current ownership of the
    planet unless the passed empire value is a simple int matching fo.empireID(), because in most cases we are concerned
    about (i) visibility to us of a planet we do not own, or (ii) visibility by enemies of a planet we own or expect to
    own at the time we are making the visibility projection for (even if they may own it right now).  The only case
    where current ownership matters is when we are considering whether to abort a colonization mission, which might be
    for a planet we already own.

    :param planet_id: required, the planet of concern
    :type planet_id: int
    :param species_name: will override the existing planet species if provided
    :type species_name: str
    :param empire: empire ID (or list of empire IDs) whose detection ability is of concern
    :type empire: int | list[int]
    :param future_stealth_bonus: can specify a projected future stealth bonus, such as from a stealth tech
    :type future_stealth_bonus: int
    :param default_result: generally for offensive assessments should be False, for defensive should be True
    :type default_result: bool
    :return: whether the planet is predicted to be detectable
    :rtype: bool
    """
    # The future_stealth_bonus can be used if the AI knows it has researched techs that would grant a stealth bonus to
    # the planet once it was colonized/captured

    planet = fo.getUniverse().getPlanet(planet_id)
    if not planet:
        error("Couldn't retrieve planet ID %d." % planet_id)
        return default_result
    if species_name is None:
        species_name = planet.speciesName

    # in case we are checking about aborting a colonization mission
    if empire == fo.empireID() and planet.ownedBy(empire):
        return True

    species = fo.getSpecies(species_name)
    if species:
        species_tags = species.tags
    elif species_name == "":
        species_tags = []
    else:
        error("Couldn't retrieve species named '%s'." % species_name)
        return default_result

    # could just check stealth meter, but this approach might allow us to plan ahead a bit even if the planet
    # is temporarily stealth boosted by temporary effects like ion storm
    planet_stealth = AIDependencies.BASE_PLANET_STEALTH
    if planet.specials:
        planet_stealth += max([
            AIDependencies.STEALTH_SPECIAL_STRENGTHS.get(_spec, 0)
            for _spec in planet.specials
        ])
    # TODO: check planet buildings for stealth bonuses

    # if the planet already has an existing stealth special, then the most common situation is that it would be
    # overlapping with or superseded by the future_stealth_bonus, not additive with it.
    planet_stealth = max(
        planet_stealth,
        AIDependencies.BASE_PLANET_STEALTH + future_stealth_bonus)

    total_stealth = planet_stealth + sum([
        AIDependencies.STEALTH_STRENGTHS_BY_SPECIES_TAG.get(tag, 0)
        for tag in species_tags
    ])
    if isinstance(empire, int):
        empire_detection = get_empire_detection(empire)
    else:
        empire_detection = get_max_empire_detection(empire)
    return total_stealth < empire_detection
示例#37
0
def generateResearchOrders():
    "generate research orders"

    universe=fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    print "Research Queue Management:"
    tRP = empire.resourceProduction(fo.resourceType.research)
    print "\nTotal Current Research Points: %.2f\n"%tRP
    print "Techs researched and available for use:"
    completedTechs = sorted(list(getCompletedTechs()))
    tlist = completedTechs+3*[" "]
    tlines = zip( tlist[0::3],  tlist[1::3],  tlist[2::3])
    for tline in tlines:
        print "%25s  %25s  %25s"%tline
    print""
    
    #
    # report techs currently at head of research queue
    #
    researchQueue = empire.researchQueue
    researchQueueList = getResearchQueueTechs()
    inProgressTechs.clear()
    if  researchQueueList:
        print "Techs currently at head of Research Queue:"
        for element in list(researchQueue)[:10]:
            if element.allocation > 0.0:
                inProgressTechs[element.tech]=True
            thisTech=fo.getTech(element.tech)
            if not thisTech:
                print "Error: can't retrieve tech ",  element.tech
                continue
            missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq not in completedTechs]
            #unlockedItems = [(uli.name,  uli.type) for uli in thisTech.unlockedItems]
            unlockedItems = [uli.name for uli in thisTech.unlockedItems]
            if not missingPrereqs:
                print "    %25s  allocated %6.2f RP -- unlockable items: %s "%(element.tech,  element.allocation,  unlockedItems)
            else:
                print "    %25s  allocated %6.2f RP   --  missing preReqs: %s   -- unlockable items: %s "%(element.tech,  element.allocation,  missingPrereqs,  unlockedItems)
        print ""
    #
    # set starting techs, or after turn 100 add any additional default techs
    #
    if (fo.currentTurn()==1) or ((fo.currentTurn()<5) and (len(researchQueueList)==0) ):
        research_index = get_research_index()
        newtech = TechsListsAI.primary_meta_techs(index = research_index)
        print "Empire %s (%d) is selecting research index %d"%(empire.name,  empireID,  research_index)
        #pLTsToEnqueue = (set(newtech)-(set(completedTechs)|set(researchQueueList)))
        pLTsToEnqueue = newtech[:]
        techBase = set(completedTechs+researchQueueList)
        techsToAdd=[]
        for tech in pLTsToEnqueue:
            if (tech not in  techBase):
                thisTech=fo.getTech(tech)
                if thisTech is None:
                    print "Error: desired tech '%s' appears to not exist"%tech
                    continue
                missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq not in techBase]
                techsToAdd.extend( missingPrereqs+[tech] )
                techBase.update(  missingPrereqs+[tech]  )
        cumCost=0
        print "  Enqueued Tech:  %20s \t\t %8s \t %s"%("Name",  "Cost",  "CumulativeCost")
        for name in techsToAdd:
            try:
                enqueueRes = fo.issueEnqueueTechOrder(name, -1)
                if enqueueRes == 1:
                    thisTech=fo.getTech(name)
                    thisCost=0
                    if thisTech:
                        thisCost = thisTech.researchCost(empireID)
                        cumCost += thisCost
                    print "    Enqueued Tech: %20s \t\t %8.0f \t %8.0f" % ( name,  thisCost,  cumCost)
                else:
                    print "    Error: failed attempt to enqueued Tech: " + name
            except:
                print "    Error: failed attempt to enqueued Tech: " + name
                print "    Error: exception triggered and caught:  ",  traceback.format_exc()
        if foAI.foAIstate.aggression <= fo.aggression.cautious:
            researchQueueList = getResearchQueueTechs()
            defTechs = TechsListsAI.defense_techs_1()
            for defTech in defTechs:
                if   defTech not in researchQueueList[:5]  and  empire.getTechStatus(defTech) != fo.techStatus.complete:
                    res=fo.issueEnqueueTechOrder(defTech, min(3,  len(researchQueueList)))
                    print "Empire is very defensive,  so attempted to fast-track %s,  got result %d"%(defTech, res)
        if False and foAI.foAIstate.aggression >= fo.aggression.aggressive: #with current stats of Conc Camps, disabling this fast-track
            researchQueueList = getResearchQueueTechs()
            if "CON_CONC_CAMP" in researchQueueList:
                insertIdx = min(40,  researchQueueList.index("CON_CONC_CAMP"))
            else:
                insertIdx=max(0,  min(40, len(researchQueueList)-10))
            if "SHP_DEFLECTOR_SHIELD" in researchQueueList:
                insertIdx = min(insertIdx,  researchQueueList.index("SHP_DEFLECTOR_SHIELD"))
            for ccTech in [  "CON_ARCH_PSYCH",  "CON_CONC_CAMP"]:
                if   ccTech not in researchQueueList[:insertIdx+1]  and  empire.getTechStatus(ccTech) != fo.techStatus.complete:
                    res=fo.issueEnqueueTechOrder(ccTech, insertIdx)
                    print "Empire is very aggressive,  so attempted to fast-track %s,  got result %d"%(ccTech, res)

        print""

        generateDefaultResearchOrders()
        print "\n\nAll techs:"
        alltechs = fo.techs() # returns names of all techs
        for tname in alltechs:
            print tname
        print "\n-------------------------------\nAll unqueued techs:"
        #coveredTechs = newtech+completedTechs
        for tname in [tn for tn in alltechs if tn not in techBase]:
            print tname

    elif fo.currentTurn() >100:
        generateDefaultResearchOrders()

    researchQueueList = getResearchQueueTechs()
    num_techs_accelerated = 1 # will ensure leading tech doesn't get dislodged
    gotGGG = empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete
    gotSymBio = empire.getTechStatus("GRO_SYMBIOTIC_BIO") == fo.techStatus.complete
    gotXenoGen = empire.getTechStatus("GRO_XENO_GENETICS") == fo.techStatus.complete
    #
    # Consider accelerating techs; priority is
    # Supply/Detect range
    # xeno arch
    # ast / GG
    # gro xeno gen
    # distrib thought
    # quant net
    # pro sing gen
    # death ray 1 cleanup

    #
    # Supply range and detection range
    if True: #just to help with cold-folding /  organization
        if len(foAI.foAIstate.colonisablePlanetIDs)==0:
            bestColonySiteScore = 0
        else:
            bestColonySiteScore= foAI.foAIstate.colonisablePlanetIDs[0][1]
        if len(foAI.foAIstate.colonisableOutpostIDs)==0:
            bestOutpostSiteScore = 0
        else:
            bestOutpostSiteScore= foAI.foAIstate.colonisableOutpostIDs[0][1]
        needImprovedScouting = ( bestColonySiteScore <150  or   bestOutpostSiteScore < 200 )

        if needImprovedScouting:
            if (empire.getTechStatus("CON_ORBITAL_CON") != fo.techStatus.complete):
                if  ( "CON_ORBITAL_CON" not in researchQueueList[:1 + num_techs_accelerated]  ) and  (
                                (empire.getTechStatus("PRO_FUSION_GEN") == fo.techStatus.complete) or ( "PRO_FUSION_GEN"  in researchQueueList[:1+num_techs_accelerated]  )):
                    res=fo.issueEnqueueTechOrder("CON_ORBITAL_CON", num_techs_accelerated)
                    num_techs_accelerated += 1
                    print "Empire has poor colony/outpost prospects,  so attempted to fast-track %s,  got result %d"%("CON_ORBITAL_CON", res)
            elif (empire.getTechStatus("CON_CONTGRAV_ARCH") != fo.techStatus.complete):
                if  ( "CON_CONTGRAV_ARCH" not in researchQueueList[:1+num_techs_accelerated]  ) and  ((empire.getTechStatus("CON_METRO_INFRA") == fo.techStatus.complete)):
                    for supply_tech in [_s_tech for _s_tech in ["CON_ARCH_MONOFILS",  "CON_CONTGRAV_ARCH"] if  (empire.getTechStatus(_s_tech) != fo.techStatus.complete)]:
                        res=fo.issueEnqueueTechOrder(supply_tech, num_techs_accelerated)
                        num_techs_accelerated += 1
                        print "Empire has poor colony/outpost prospects,  so attempted to fast-track %s,  got result %d"%(supply_tech, res)
            elif (empire.getTechStatus("CON_GAL_INFRA") != fo.techStatus.complete):
                if  ( "CON_GAL_INFRA" not in researchQueueList[:1+num_techs_accelerated]  ) and  ((empire.getTechStatus("PRO_SINGULAR_GEN") == fo.techStatus.complete)):
                    res=fo.issueEnqueueTechOrder("CON_GAL_INFRA", num_techs_accelerated)
                    num_techs_accelerated += 1
                    print "Empire has poor colony/outpost prospects,  so attempted to fast-track %s,  got result %d"%("CON_GAL_INFRA", res)
            else:
                pass
            researchQueueList = getResearchQueueTechs()
                #could add more supply tech
            
            if False and (empire.getTechStatus("SPY_DETECT_2") != fo.techStatus.complete): #disabled for now, detect2
                if  ( "SPY_DETECT_2" not in researchQueueList[:2+num_techs_accelerated]  ) and  (empire.getTechStatus("PRO_FUSION_GEN") == fo.techStatus.complete) :
                    if  ( "CON_ORBITAL_CON" not in researchQueueList[:1+num_techs_accelerated]  ):
                        res=fo.issueEnqueueTechOrder("SPY_DETECT_2", num_techs_accelerated)
                    else:
                        CO_idx = researchQueueList.index( "CON_ORBITAL_CON")
                        res=fo.issueEnqueueTechOrder("SPY_DETECT_2", CO_idx+1)
                    num_techs_accelerated += 1
                    print "Empire has poor colony/outpost prospects,  so attempted to fast-track %s,  got result %d"%("CON_ORBITAL_CON", res)
                researchQueueList = getResearchQueueTechs()

    #
    # check to accelerate xeno_arch
    if True: #just to help with cold-folding /  organization
        if ColonisationAI.gotRuins and empire.getTechStatus("LRN_XENOARCH") != fo.techStatus.complete:
            if "LRN_ARTIF_MINDS" in researchQueueList:
                insert_idx = 7+ researchQueueList.index("LRN_ARTIF_MINDS")
            elif "GRO_SYMBIOTIC_BIO" in researchQueueList:
                insert_idx = researchQueueList.index("GRO_SYMBIOTIC_BIO") + 1 
            else:
                insert_idx = num_techs_accelerated
            if "LRN_XENOARCH" not in researchQueueList[:insert_idx]:
                for xenoTech in [  "LRN_XENOARCH",  "LRN_TRANSLING_THT",  "LRN_PHYS_BRAIN" ,  "LRN_ALGO_ELEGANCE"]:
                    if (empire.getTechStatus(xenoTech) != fo.techStatus.complete) and (  xenoTech  not in researchQueueList[:(insert_idx+4)])  :
                        res=fo.issueEnqueueTechOrder(xenoTech,insert_idx)
                        num_techs_accelerated += 1
                        print "ANCIENT_RUINS: have an ancient ruins, so attempted to fast-track %s  to enable LRN_XENOARCH,  got result %d"%(xenoTech, res)
                researchQueueList = getResearchQueueTechs()

    #
    # check to accelerate asteroid or GG tech
    if True: #just to help with cold-folding /  organization
        if ColonisationAI.gotAst and empire.getTechStatus("SHP_ASTEROID_HULLS") != fo.techStatus.complete and (
                        ("SHP_ASTEROID_HULLS" not in researchQueueList[num_techs_accelerated])): #if needed but not top item, will block acceleration of pro_orb_gen
            if ("SHP_ASTEROID_HULLS" not in researchQueueList[:2+num_techs_accelerated]):
                if "GRO_SYMBIOTIC_BIO" in researchQueueList:
                    insert_idx = 1+ researchQueueList.index("GRO_SYMBIOTIC_BIO")
                else:
                    insert_idx = num_techs_accelerated
                for ast_tech in ["SHP_ASTEROID_HULLS", "PRO_MICROGRAV_MAN"]:
                    if (empire.getTechStatus(ast_tech) != fo.techStatus.complete) and (  ast_tech  not in researchQueueList[:insert_idx+2])  :
                        res=fo.issueEnqueueTechOrder(ast_tech,insert_idx)
                        num_techs_accelerated += 1
                        print "Asteroids: have colonized an asteroid belt, so attempted to fast-track %s ,  got result %d"%(ast_tech, res)
                researchQueueList = getResearchQueueTechs()
        elif ColonisationAI.gotGG and empire.getTechStatus("PRO_ORBITAL_GEN") != fo.techStatus.complete  and (
                    "PRO_ORBITAL_GEN" not in researchQueueList[:3+num_techs_accelerated]):
            if "GRO_SYMBIOTIC_BIO" in researchQueueList:
                insert_idx = 1+ researchQueueList.index("GRO_SYMBIOTIC_BIO")
            else:
                insert_idx = num_techs_accelerated
            res=fo.issueEnqueueTechOrder("PRO_ORBITAL_GEN",insert_idx)
            num_techs_accelerated += 1
            print "GasGiant: have colonized a gas giant, so attempted to fast-track %s, got result %d"%("PRO_ORBITAL_GEN", res)
            researchQueueList = getResearchQueueTechs()
    #
    # assess if our empire has any non-lousy colonizers, & boost gro_xeno_gen if we don't
    if True: #just to help with cold-folding /  organization
        if gotGGG and gotSymBio and (not gotXenoGen) and foAI.foAIstate.aggression >= fo.aggression.cautious:
            mostAdequate=0
            for specName in ColonisationAI.empireColonizers:
                environs={}
                thisSpec = fo.getSpecies(specName)
                if not thisSpec: 
                    continue
                for ptype in [fo.planetType.swamp,  fo.planetType.radiated,  fo.planetType.toxic,  fo.planetType.inferno,  fo.planetType.barren,  fo.planetType.tundra,  fo.planetType.desert,  fo.planetType.terran,  fo.planetType.ocean,  fo.planetType.asteroids]:
                    environ=thisSpec.getPlanetEnvironment(ptype)
                    environs.setdefault(environ, []).append(ptype)
                mostAdequate = max(mostAdequate,  len(environs.get( fo.planetEnvironment.adequate, [])))
            if mostAdequate==0:
                insert_idx = num_techs_accelerated
                for xgTech in [ "GRO_XENO_GENETICS", "GRO_GENETIC_ENG" ]:
                    if   xgTech not in researchQueueList[:1+num_techs_accelerated]  and  empire.getTechStatus(xgTech) != fo.techStatus.complete:
                        res=fo.issueEnqueueTechOrder(xgTech, insert_idx)
                        num_techs_accelerated += 1
                        print "Empire has poor colonizers,  so attempted to fast-track %s,  got result %d"%(xgTech, res)
                researchQueueList = getResearchQueueTechs()
    #
    # check to accelerate distrib thought
    if True: #just to help with cold-folding /  organization
        if (empire.getTechStatus("LRN_DISTRIB_THOUGHT") != fo.techStatus.complete):
            got_telepathy = False
            for specName in ColonisationAI.empireSpecies:
                thisSpec=fo.getSpecies(specName)
                if thisSpec and ("TELEPATHIC" in list(thisSpec.tags)):
                    got_telepathy = True
                    break
            if ((foAI.foAIstate.aggression > fo.aggression.cautious) and (empire.population() > ([300, 100][got_telepathy]))):
                insert_idx = num_techs_accelerated
                for dt_ech in [ "LRN_DISTRIB_THOUGHT", "LRN_PSIONICS", "LRN_TRANSLING_THT",  "LRN_PHYS_BRAIN" ]:
                    if   dt_ech not in researchQueueList[:4+num_techs_accelerated]  and  empire.getTechStatus(dt_ech) != fo.techStatus.complete:
                        res=fo.issueEnqueueTechOrder(dt_ech, insert_idx)
                        num_techs_accelerated += 1
                        fmt_str = "Empire has a telepathic race, so attempted to fast-track %s (got result %d)"
                        fmt_str += " with current target_RP %.1f and current pop %.1f, on turn %d"
                        print fmt_str%( dt_ech, res,  tRP,  empire.population(),  fo.currentTurn())
                researchQueueList = getResearchQueueTechs()
    #
    # check to accelerate quant net
    if True: #just to help with cold-folding /  organization
        if (foAI.foAIstate.aggression > fo.aggression.cautious) and( ColonisationAI.empire_status.get('researchers', 0) >= 40 ):
            if (empire.getTechStatus("LRN_QUANT_NET") != fo.techStatus.complete):
                insert_idx = num_techs_accelerated
                for qnTech in [ "LRN_NDIM_SUBSPACE", "LRN_QUANT_NET" ]:
                    if   qnTech not in researchQueueList[:2+num_techs_accelerated]  and  empire.getTechStatus(qnTech) != fo.techStatus.complete:
                        res=fo.issueEnqueueTechOrder(qnTech, insert_idx)
                        num_techs_accelerated += 1
                        print "Empire has many researchers, so attempted to fast-track %s (got result %d) on turn %d"%(qnTech, res,  fo.currentTurn())
                researchQueueList = getResearchQueueTechs()

    #
    # if we own a blackhole, accelerate sing_gen and conc camp
    if True: #just to help with cold-folding /  organization
        if ( fo.currentTurn() >50 and len (AIstate.empireStars.get(fo.starType.blackHole,  []))!=0 and 
                    foAI.foAIstate.aggression > fo.aggression.cautious and (empire.getTechStatus(AIDependencies.sing_tech_name) != fo.techStatus.complete) ):
            #sing_tech_list = [  "LRN_GRAVITONICS" ,  "PRO_SINGULAR_GEN"]   # formerly also "CON_ARCH_PSYCH",  "CON_CONC_CAMP",  
            sing_gen_tech = fo.getTech(AIDependencies.sing_tech_name)
            sing_tech_list =  [pre_req for pre_req in sing_gen_tech.recursivePrerequisites(empireID) if (empire.getTechStatus(pre_req) != fo.techStatus.complete) ]
            sing_tech_list += [ AIDependencies.sing_tech_name ]
            for singTech in sing_tech_list:
                if (  singTech  not in researchQueueList[:num_techs_accelerated+1  ])  :
                    res=fo.issueEnqueueTechOrder(singTech,num_techs_accelerated)
                    num_techs_accelerated += 1
                    print "have a black hole star outpost/colony, so attempted to fast-track %s,  got result %d"%(singTech, res)
            researchQueueList = getResearchQueueTechs()

    #
    # if got deathray from Ruins, remove most prereqs from queue
    if True: #just to help with cold-folding /  organization
        if  empire.getTechStatus("SHP_WEAPON_4_1" ) == fo.techStatus.complete:
            thisTech=fo.getTech("SHP_WEAPON_4_1")
            if thisTech:
                missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq in researchQueueList]
                if  len(missingPrereqs) > 2 : #leave plasma 4 and 3 if up to them already
                    for preReq in missingPrereqs:  #sorted(missingPrereqs,  reverse=True)[2:]
                        if preReq in researchQueueList:
                            res = fo.issueDequeueTechOrder(preReq)
                    if "SHP_WEAPON_4_2" in researchQueueList: #(should be)
                        idx = researchQueueList.index("SHP_WEAPON_4_2")
                        res=fo.issueEnqueueTechOrder("SHP_WEAPON_4_2",  max(0,  idx-15) )
            researchQueueList = getResearchQueueTechs()
示例#38
0
def colony_detectable_by_empire(planet_id,
                                species_name=None,
                                empire_id=ALL_EMPIRES,
                                future_stealth_bonus=0,
                                default_result=True):
    """
    Predicts if a planet/colony is/will-be detectable by an empire
    :param planet_id: required, the planet of concern
    :type planet_id: int
    :param species_name: will override the existing planet species if provided
    :type species_name: str
    :param empire_id: empire whose detection ability is of concern
    :type empire_id: int
    :param future_stealth_bonus: can specify a projected future stealth bonus, such as from a stealth tech
    :type future_stealth_bonus: int
    :param default_result: generally for offensive assessments should be False, for defensive should be True
    :type default_result: bool
    :return: whether the planet is predicted to be detectable
    :rtype: bool
    """
    # The future_stealth_bonus can be used if the AI knows it has researched techs that would grant a stealth bonus to
    # the planet once it was colonized/captured

    empire_detection = get_empire_detection(empire_id)
    planet = fo.getUniverse().getPlanet(planet_id)
    if not planet:
        error("Couldn't retrieve planet ID %d." % planet_id)
        return default_result
    if species_name is None:
        species_name = planet.speciesName

    # in case we are checking about aborting a colonization mission
    if empire_id == fo.empireID() and planet.ownedBy(empire_id):
        return True

    species = fo.getSpecies(species_name)
    if species:
        species_tags = species.tags
    elif species_name == "":
        species_tags = []
    else:
        error("Couldn't retrieve species named '%s'." % species_name)
        return default_result

    # could just check stealth meter, but this approach might allow us to plan ahead a bit even if the planet
    # is temporarily stealth boosted by temporary effects like ion storm
    planet_stealth = max([AIDependencies.BASE_PLANET_STEALTH] + [
        AIDependencies.STEALTH_SPECIAL_STRENGTHS.get(_spec, 0)
        for _spec in planet.specials
    ])
    # TODO: check planet buildings for stealth bonuses

    # if the planet already has an existing stealth special, then the most common situation is that it would be
    # overlapping with or superseded by the future_stealth_bonus, not additive with it.
    planet_stealth = max(
        planet_stealth,
        AIDependencies.BASE_PLANET_STEALTH + future_stealth_bonus)

    total_stealth = planet_stealth + sum([
        AIDependencies.STEALTH_STRENGTHS_BY_SPECIES_TAG.get(tag, 0)
        for tag in species_tags
    ])
    return total_stealth < empire_detection
示例#39
0
def generateResearchOrders():
    global inProgressTechs
    "generate research orders"
    universe=fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    print "Research Queue Management:"
    tRP = empire.resourceProduction(fo.resourceType.research)
    print "\nTotal Current Research Points: %.2f\n"%tRP
    print "Techs researched and available for use:"
    completedTechs = sorted(list(getCompletedTechs()))
    tlist = completedTechs+3*[" "]
    tlines = zip( tlist[0::3],  tlist[1::3],  tlist[2::3])
    for tline in tlines:
        print "%25s  %25s  %25s"%tline
    print""
    
    if tRP >= 20  and foAI.foAIstate.aggression > 1:
        researchQueueList = getResearchQueueTechs()
        if (empire.getTechStatus("LRN_PSIONICS") != fo.techStatus.complete)  and ( "LRN_PSIONICS" not in researchQueueList[:5]  )  :
            for specName in ColonisationAI.empireSpecies:
                thisSpec=fo.getSpecies(specName)
                if thisSpec:
                    if "TELEPATHIC" in list(thisSpec.tags):
                        res=fo.issueEnqueueTechOrder("LRN_DISTRIB_THOUGHT", 0)
                        res=fo.issueEnqueueTechOrder("LRN_PSIONICS", 0)
                        break


    gotSymBio = empire.getTechStatus("GRO_SYMBIOTIC_BIO") == fo.techStatus.complete
    gotXenoGen = empire.getTechStatus("GRO_XENO_GENETICS") == fo.techStatus.complete
    #assess if our empire has any non-lousy colonizers, & boost gro_xeno_gen if we don't
    if gotSymBio and (not gotXenoGen) and foAI.foAIstate.aggression!=0:
        mostAdequate=0
        for specName in ColonisationAI.empireColonizers:
            environs={}
            thisSpec = fo.getSpecies(specName)
            if not thisSpec: continue
            for ptype in [fo.planetType.swamp,  fo.planetType.radiated,  fo.planetType.toxic,  fo.planetType.inferno,  fo.planetType.barren,  fo.planetType.tundra,  fo.planetType.desert,  fo.planetType.terran,  fo.planetType.ocean,  fo.planetType.asteroids]:
                environ=thisSpec.getPlanetEnvironment(ptype)
                environs.setdefault(environ, []).append(ptype)
            mostAdequate = max(mostAdequate,  len(environs.get( fo.planetEnvironment.adequate, [])))
            if mostAdequate==0:
                researchQueue = empire.researchQueue
                researchQueueList = getResearchQueueTechs()
                if "GRO_XENO_GENETICS" not in researchQueueList[:2]:
                    res=fo.issueEnqueueTechOrder("GRO_XENO_GENETICS", 0)
                    print "Empire has poor colonizers,  so attempted to fast-track GRO_XENO_GENETICS,  got result %d"%res
    
    
    researchQueue = empire.researchQueue
    researchQueueList = getResearchQueueTechs()
    inProgressTechs.clear()
    if  researchQueueList:
        print "Techs currently at head of Research Queue:"
        for element in list(researchQueue)[:10]:
            if element.allocation > 0.0:
                inProgressTechs[element.tech]=True
            thisTech=fo.getTech(element.tech)
            missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq not in completedTechs]
            unlockedItems = [(uli.name,  uli.type) for uli in thisTech.unlockedItems]
            if not missingPrereqs:
                print "    %25s  allocated %6.2f RP -- unlockable items: %s "%(element.tech,  element.allocation,  unlockedItems)
            else:
                print "    %25s  allocated %6.2f RP   --  missing preReqs: %s   -- unlockable items: %s "%(element.tech,  element.allocation,  missingPrereqs,  unlockedItems)
        print ""
    if fo.currentTurn()==1:
        newtech = TechsListsAI.primaryMetaTechsList()
        #pLTsToEnqueue = (set(newtech)-(set(completedTechs)|set(researchQueueList)))
        pLTsToEnqueue = newtech[:]
        techBase = set(completedTechs+researchQueueList)
        techsToAdd=[]
        for tech in pLTsToEnqueue:
            if (tech not in  techBase): 
                thisTech=fo.getTech(tech)
                if thisTech is None:
                    continue
                missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq not in techBase] 
                techsToAdd.extend( missingPrereqs+[tech] )
                techBase.update(  missingPrereqs+[tech]  )
        for name in techsToAdd:
            try:
                enqueueRes = fo.issueEnqueueTechOrder(name, -1)
                if enqueueRes == 1:
                    print "    Enqueued Tech: " + name
                else:
                    print "    Error: failed attempt to enqueued Tech: " + name
            except:
                print "    Error: failed attempt to enqueued Tech: " + name
                print "    Error: exception triggered and caught:  ",  traceback.format_exc()
        print""
        generateDefaultResearchOrders()
        print "\n\nAll techs:"
        alltechs = fo.techs() # returns names of all techs
        for tname in alltechs:
            print tname
        print "\n-------------------------------\nAll unqueued techs:"
        coveredTechs = newtech+completedTechs
        for tname in [tn for tn in alltechs if tn not in coveredTechs]:
            print tname

    elif fo.currentTurn() >50:
        generateDefaultResearchOrders()
示例#40
0
def generate_research_orders():
    """generate research orders"""
    report_adjustments = False
    empire = fo.getEmpire()
    empire_id = empire.empireID
    enemies_sighted = foAI.foAIstate.misc.get('enemies_sighted', {})
    galaxy_is_sparse = ColonisationAI.galaxy_is_sparse()
    print "Research Queue Management:"
    resource_production = empire.resourceProduction(fo.resourceType.research)
    print "\nTotal Current Research Points: %.2f\n" % resource_production
    print "Techs researched and available for use:"
    completed_techs = sorted(list(get_completed_techs()))
    tlist = completed_techs + 3 * [" "]
    tlines = zip(tlist[0::3], tlist[1::3], tlist[2::3])
    for tline in tlines:
        print "%25s %25s %25s" % tline
    print

    #
    # report techs currently at head of research queue
    #
    research_queue = empire.researchQueue
    research_queue_list = get_research_queue_techs()
    inProgressTechs.clear()
    tech_turns_left = {}
    if research_queue_list:
        print "Techs currently at head of Research Queue:"
        for element in list(research_queue)[:10]:
            tech_turns_left[element.tech] = element.turnsLeft
            if element.allocation > 0.0:
                inProgressTechs[element.tech] = True
            this_tech = fo.getTech(element.tech)
            if not this_tech:
                print "Error: can't retrieve tech ", element.tech
                continue
            missing_prereqs = [
                preReq
                for preReq in this_tech.recursivePrerequisites(empire_id)
                if preReq not in completed_techs
            ]
            # unlocked_items = [(uli.name, uli.type) for uli in this_tech.unlocked_items]
            unlocked_items = [uli.name for uli in this_tech.unlockedItems]
            if not missing_prereqs:
                print "    %25s allocated %6.2f RP -- unlockable items: %s " % (
                    element.tech, element.allocation, unlocked_items)
            else:
                print "    %25s allocated %6.2f RP -- missing preReqs: %s -- unlockable items: %s " % (
                    element.tech, element.allocation, missing_prereqs,
                    unlocked_items)
        print
    #
    # set starting techs, or after turn 100 add any additional default techs
    #
    if (fo.currentTurn() == 1) or ((fo.currentTurn() < 5) and
                                   (len(research_queue_list) == 0)):
        research_index = get_research_index()
        new_tech = TechsListsAI.sparse_galaxy_techs(
            research_index
        ) if galaxy_is_sparse else TechsListsAI.primary_meta_techs(
            research_index)
        print "Empire %s (%d) is selecting research index %d" % (
            empire.name, empire_id, research_index)
        # techs_to_enqueue = (set(new_tech)-(set(completed_techs)|set(research_queue_list)))
        techs_to_enqueue = new_tech[:]
        tech_base = set(completed_techs + research_queue_list)
        techs_to_add = []
        for tech in techs_to_enqueue:
            if tech not in tech_base:
                this_tech = fo.getTech(tech)
                if this_tech is None:
                    print "Error: desired tech '%s' appears to not exist" % tech
                    continue
                missing_prereqs = [
                    preReq
                    for preReq in this_tech.recursivePrerequisites(empire_id)
                    if preReq not in tech_base
                ]
                techs_to_add.extend(missing_prereqs + [tech])
                tech_base.update(missing_prereqs + [tech])
        cum_cost = 0
        print "  Enqueued Tech: %20s \t\t %8s \t %s" % ("Name", "Cost",
                                                        "CumulativeCost")
        for name in techs_to_add:
            try:
                enqueue_res = fo.issueEnqueueTechOrder(name, -1)
                if enqueue_res == 1:
                    this_tech = fo.getTech(name)
                    this_cost = 0
                    if this_tech:
                        this_cost = this_tech.researchCost(empire_id)
                        cum_cost += this_cost
                    print "    Enqueued Tech: %20s \t\t %8.0f \t %8.0f" % (
                        name, this_cost, cum_cost)
                else:
                    print "    Error: failed attempt to enqueued Tech: " + name
            except:
                print "    Error: failed attempt to enqueued Tech: " + name
                print "    Error: exception triggered and caught: ", traceback.format_exc(
                )
        if foAI.foAIstate.aggression <= fo.aggression.cautious:
            research_queue_list = get_research_queue_techs()
            def_techs = TechsListsAI.defense_techs_1()
            for def_tech in def_techs:
                if def_tech not in research_queue_list[:
                                                       5] and not tech_is_complete(
                                                           def_tech):
                    res = fo.issueEnqueueTechOrder(
                        def_tech, min(3, len(research_queue_list)))
                    print "Empire is very defensive, so attempted to fast-track %s, got result %d" % (
                        def_tech, res)
        if False and foAI.foAIstate.aggression >= fo.aggression.aggressive:  # with current stats of Conc Camps, disabling this fast-track
            research_queue_list = get_research_queue_techs()
            if "CON_CONC_CAMP" in research_queue_list:
                insert_idx = min(40,
                                 research_queue_list.index("CON_CONC_CAMP"))
            else:
                insert_idx = max(0, min(40, len(research_queue_list) - 10))
            if "SHP_DEFLECTOR_SHIELD" in research_queue_list:
                insert_idx = min(
                    insert_idx,
                    research_queue_list.index("SHP_DEFLECTOR_SHIELD"))
            for cc_tech in ["CON_ARCH_PSYCH", "CON_CONC_CAMP"]:
                if cc_tech not in research_queue_list[:insert_idx +
                                                      1] and not tech_is_complete(
                                                          cc_tech):
                    res = fo.issueEnqueueTechOrder(cc_tech, insert_idx)
                    msg = "Empire is very aggressive, so attempted to fast-track %s, got result %d" % (
                        cc_tech, res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg

        print ""

        generate_default_research_order()
        print "\n\nAll techs:"
        alltechs = fo.techs()  # returns names of all techs
        for tname in alltechs:
            print tname
        print "\n-------------------------------\nAll unqueued techs:"
        # coveredTechs = new_tech+completed_techs
        for tname in [tn for tn in alltechs if tn not in tech_base]:
            print tname

    elif fo.currentTurn() > 100:
        generate_default_research_order()

    research_queue_list = get_research_queue_techs()
    num_techs_accelerated = 1  # will ensure leading tech doesn't get dislodged
    got_ggg_tech = tech_is_complete("PRO_ORBITAL_GEN")
    got_sym_bio = tech_is_complete("GRO_SYMBIOTIC_BIO")
    got_xeno_gen = tech_is_complete("GRO_XENO_GENETICS")
    #
    # Consider accelerating techs; priority is
    # Supply/Detect range
    # xeno arch
    # ast / GG
    # gro xeno gen
    # distrib thought
    # quant net
    # pro sing gen
    # death ray 1 cleanup

    #
    # Supply range and detection range
    if False:  # disabled for now, otherwise just to help with cold-folding / organization
        if len(foAI.foAIstate.colonisablePlanetIDs) == 0:
            best_colony_site_score = 0
        else:
            best_colony_site_score = foAI.foAIstate.colonisablePlanetIDs.items(
            )[0][1]
        if len(foAI.foAIstate.colonisableOutpostIDs) == 0:
            best_outpost_site_score = 0
        else:
            best_outpost_site_score = foAI.foAIstate.colonisableOutpostIDs.items(
            )[0][1]
        need_improved_scouting = (best_colony_site_score < 150
                                  or best_outpost_site_score < 200)

        if need_improved_scouting:
            if not tech_is_complete("CON_ORBITAL_CON"):
                num_techs_accelerated += 1
                if ("CON_ORBITAL_CON"
                        not in research_queue_list[:1 + num_techs_accelerated]
                    ) and (tech_is_complete("PRO_FUSION_GEN") or
                           ("PRO_FUSION_GEN"
                            in research_queue_list[:1 +
                                                   num_techs_accelerated])):
                    res = fo.issueEnqueueTechOrder("CON_ORBITAL_CON",
                                                   num_techs_accelerated)
                    msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % (
                        "CON_ORBITAL_CON", res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
            elif not tech_is_complete("CON_CONTGRAV_ARCH"):
                num_techs_accelerated += 1
                if ("CON_CONTGRAV_ARCH"
                        not in research_queue_list[:1 + num_techs_accelerated]
                    ) and (tech_is_complete("CON_METRO_INFRA")):
                    for supply_tech in [
                            _s_tech for _s_tech in
                        ["CON_ARCH_MONOFILS", "CON_CONTGRAV_ARCH"]
                            if not tech_is_complete(_s_tech)
                    ]:
                        res = fo.issueEnqueueTechOrder(supply_tech,
                                                       num_techs_accelerated)
                        msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % (
                            supply_tech, res)
                        if report_adjustments:
                            chat_human(msg)
                        else:
                            print msg
            elif not tech_is_complete("CON_GAL_INFRA"):
                num_techs_accelerated += 1
                if ("CON_GAL_INFRA"
                        not in research_queue_list[:1 + num_techs_accelerated]
                    ) and (tech_is_complete("PRO_SINGULAR_GEN")):
                    res = fo.issueEnqueueTechOrder("CON_GAL_INFRA",
                                                   num_techs_accelerated)
                    msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % (
                        "CON_GAL_INFRA", res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
            else:
                pass
            research_queue_list = get_research_queue_techs()
            # could add more supply tech

            if False and not tech_is_complete(
                    "SPY_DETECT_2"):  # disabled for now, detect2
                num_techs_accelerated += 1
                if "SPY_DETECT_2" not in research_queue_list[:2 +
                                                             num_techs_accelerated] and tech_is_complete(
                                                                 "PRO_FUSION_GEN"
                                                             ):
                    if "CON_ORBITAL_CON" not in research_queue_list[:1 +
                                                                    num_techs_accelerated]:
                        res = fo.issueEnqueueTechOrder("SPY_DETECT_2",
                                                       num_techs_accelerated)
                    else:
                        co_idx = research_queue_list.index("CON_ORBITAL_CON")
                        res = fo.issueEnqueueTechOrder("SPY_DETECT_2",
                                                       co_idx + 1)
                    msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % (
                        "CON_ORBITAL_CON", res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
                research_queue_list = get_research_queue_techs()

    #
    # check to accelerate xeno_arch
    if True:  # just to help with cold-folding /  organization
        if (ColonisationAI.gotRuins and not tech_is_complete("LRN_XENOARCH")
                and foAI.foAIstate.aggression >= fo.aggression.typical):
            if "LRN_ARTIF_MINDS" in research_queue_list:
                insert_idx = 7 + research_queue_list.index("LRN_ARTIF_MINDS")
            elif "GRO_SYMBIOTIC_BIO" in research_queue_list:
                insert_idx = research_queue_list.index("GRO_SYMBIOTIC_BIO") + 1
            else:
                insert_idx = num_techs_accelerated
            if "LRN_XENOARCH" not in research_queue_list[:insert_idx]:
                for xenoTech in [
                        "LRN_XENOARCH", "LRN_TRANSLING_THT", "LRN_PHYS_BRAIN",
                        "LRN_ALGO_ELEGANCE"
                ]:
                    if not tech_is_complete(
                            xenoTech
                    ) and xenoTech not in research_queue_list[:(insert_idx +
                                                                4)]:
                        res = fo.issueEnqueueTechOrder(xenoTech, insert_idx)
                        num_techs_accelerated += 1
                        msg = "ANCIENT_RUINS: have an ancient ruins, so attempted to fast-track %s to enable LRN_XENOARCH, got result %d" % (
                            xenoTech, res)
                        if report_adjustments:
                            chat_human(msg)
                        else:
                            print msg
                research_queue_list = get_research_queue_techs()

    if False and not enemies_sighted:  # curently disabled
        # params = [ (tech, gate, target_slot, add_tech_list), ]
        params = [
            ("GRO_XENO_GENETICS", "PRO_EXOBOTS", "PRO_EXOBOTS",
             ["GRO_GENETIC_MED", "GRO_XENO_GENETICS"]),
            ("PRO_EXOBOTS", "PRO_SENTIENT_AUTOMATION",
             "PRO_SENTIENT_AUTOMATION", ["PRO_EXOBOTS"]),
            ("PRO_SENTIENT_AUTOMATION", "PRO_NANOTECH_PROD",
             "PRO_NANOTECH_PROD", ["PRO_SENTIENT_AUTOMATION"]),
            ("PRO_INDUSTRY_CENTER_I", "GRO_SYMBIOTIC_BIO", "GRO_SYMBIOTIC_BIO",
             ["PRO_ROBOTIC_PROD", "PRO_FUSION_GEN", "PRO_INDUSTRY_CENTER_I"]),
            ("GRO_SYMBIOTIC_BIO", "SHP_ORG_HULL", "SHP_ZORTRIUM_PLATE",
             ["GRO_SYMBIOTIC_BIO"]),
        ]
        for (tech, gate, target_slot, add_tech_list) in params:
            if tech_is_complete(tech):
                break
            if tech_turns_left.get(gate, 0) not in [
                    0, 1, 2
            ]:  # needs to exclude -1, the flag for no predicted completion
                continue
            if target_slot in research_queue_list:
                target_index = 1 + research_queue_list.index(target_slot)
            else:
                target_index = num_techs_accelerated
            for move_tech in add_tech_list:
                print "for tech %s, target_slot %s, target_index:%s ; num_techs_accelerated:%s" % (
                    move_tech, target_slot, target_index,
                    num_techs_accelerated)
                if tech_is_complete(move_tech):
                    continue
                if target_index <= num_techs_accelerated:
                    num_techs_accelerated += 1
                if move_tech not in research_queue_list[:1 + target_index]:
                    res = fo.issueEnqueueTechOrder(move_tech, target_index)
                    msg = "Research: To prioritize %s, have advanced %s to slot %d" % (
                        tech, move_tech, target_index)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
                    target_index += 1
    #
    # check to accelerate asteroid or GG tech
    if True:  # just to help with cold-folding / organization
        if ColonisationAI.got_ast:
            insert_idx = num_techs_accelerated if "GRO_SYMBIOTIC_BIO" not in research_queue_list else research_queue_list.index(
                "GRO_SYMBIOTIC_BIO")
            ast_tech = "PRO_MICROGRAV_MAN"
            if not (tech_is_complete(ast_tech)
                    or ast_tech in research_queue_list[:(1 + insert_idx)]):
                res = fo.issueEnqueueTechOrder(ast_tech, insert_idx)
                num_techs_accelerated += 1
                msg = "Asteroids: plan to colonize an asteroid belt, so attempted to fast-track %s , got result %d" % (
                    ast_tech, res)
                if report_adjustments:
                    chat_human(msg)
                else:
                    print msg
                research_queue_list = get_research_queue_techs()
            elif tech_is_complete("SHP_ZORTRIUM_PLATE"):
                insert_idx = (
                    1 + insert_idx
                ) if "LRN_FORCE_FIELD" not in research_queue_list else max(
                    1 + insert_idx,
                    research_queue_list.index("LRN_FORCE_FIELD") - 1)
                for ast_tech in [
                        "SHP_ASTEROID_HULLS", "SHP_IMPROVED_ENGINE_COUPLINGS"
                ]:
                    if not tech_is_complete(
                            ast_tech
                    ) and ast_tech not in research_queue_list[:insert_idx + 1]:
                        res = fo.issueEnqueueTechOrder(ast_tech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        msg = "Asteroids: plan to colonize an asteroid belt, so attempted to fast-track %s , got result %d" % (
                            ast_tech, res)
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()
        if ColonisationAI.got_gg and not tech_is_complete("PRO_ORBITAL_GEN"):
            fusion_idx = 0 if "PRO_FUSION_GEN" not in research_queue_list else (
                1 + research_queue_list.index("PRO_FUSION_GEN"))
            forcefields_idx = 0 if "LRN_FORCE_FIELD" not in research_queue_list else (
                1 + research_queue_list.index("LRN_FORCE_FIELD"))
            insert_idx = max(
                fusion_idx, forcefields_idx) if enemies_sighted else fusion_idx
            if "PRO_ORBITAL_GEN" not in research_queue_list[:insert_idx + 1]:
                res = fo.issueEnqueueTechOrder("PRO_ORBITAL_GEN", insert_idx)
                num_techs_accelerated += 1
                msg = "GasGiant: plan to colonize a gas giant, so attempted to fast-track %s, got result %d" % (
                    "PRO_ORBITAL_GEN", res)
                print msg
                if report_adjustments:
                    chat_human(msg)
                research_queue_list = get_research_queue_techs()
    #
    # assess if our empire has any non-lousy colonizers, & boost gro_xeno_gen if we don't
    if True:  # just to help with cold-folding / organization
        if got_ggg_tech and got_sym_bio and (
                not got_xeno_gen
        ) and foAI.foAIstate.aggression >= fo.aggression.cautious:
            most_adequate = 0
            for specName in ColonisationAI.empire_colonizers:
                environs = {}
                this_spec = fo.getSpecies(specName)
                if not this_spec:
                    continue
                for ptype in [
                        fo.planetType.swamp, fo.planetType.radiated,
                        fo.planetType.toxic, fo.planetType.inferno,
                        fo.planetType.barren, fo.planetType.tundra,
                        fo.planetType.desert, fo.planetType.terran,
                        fo.planetType.ocean, fo.planetType.asteroids
                ]:
                    environ = this_spec.getPlanetEnvironment(ptype)
                    environs.setdefault(environ, []).append(ptype)
                most_adequate = max(
                    most_adequate,
                    len(environs.get(fo.planetEnvironment.adequate, [])))
            if most_adequate == 0:
                insert_idx = num_techs_accelerated
                for xg_tech in ["GRO_XENO_GENETICS", "GRO_GENETIC_ENG"]:
                    if xg_tech not in research_queue_list[:1 +
                                                          num_techs_accelerated] and not tech_is_complete(
                                                              xg_tech):
                        res = fo.issueEnqueueTechOrder(xg_tech, insert_idx)
                        num_techs_accelerated += 1
                        msg = "Empire has poor colonizers, so attempted to fast-track %s, got result %d" % (
                            xg_tech, res)
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()
    #
    # check to accelerate distrib thought
    if True:  # just to help with cold-folding / organization
        if not tech_is_complete("LRN_DISTRIB_THOUGHT"):
            got_telepathy = False
            for specName in ColonisationAI.empire_species:
                this_spec = fo.getSpecies(specName)
                if this_spec and ("TELEPATHIC" in list(this_spec.tags)):
                    got_telepathy = True
                    break
            if (foAI.foAIstate.aggression >
                    fo.aggression.cautious) and (empire.population() >
                                                 ([300, 100][got_telepathy])):
                insert_idx = num_techs_accelerated
                for dt_ech in [
                        "LRN_PHYS_BRAIN", "LRN_TRANSLING_THT", "LRN_PSIONICS",
                        "LRN_DISTRIB_THOUGHT"
                ]:
                    if dt_ech not in research_queue_list[:insert_idx +
                                                         2] and not tech_is_complete(
                                                             dt_ech):
                        res = fo.issueEnqueueTechOrder(dt_ech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        fmt_str = "Empire has a telepathic race, so attempted to fast-track %s (got result %d)"
                        fmt_str += " with current target_RP %.1f and current pop %.1f, on turn %d"
                        msg = fmt_str % (dt_ech, res, resource_production,
                                         empire.population(), fo.currentTurn())
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()
    #
    # check to accelerate quant net
    if False:  # disabled for now, otherwise just to help with cold-folding / organization
        if (foAI.foAIstate.aggression > fo.aggression.cautious) and (
                ColonisationAI.empire_status.get('researchers', 0) >= 40):
            if not tech_is_complete("LRN_QUANT_NET"):
                insert_idx = num_techs_accelerated  # TODO determine min target slot if reenabling
                for qnTech in ["LRN_NDIM_SUBSPACE", "LRN_QUANT_NET"]:
                    if qnTech not in research_queue_list[:insert_idx +
                                                         2] and not tech_is_complete(
                                                             qnTech):
                        res = fo.issueEnqueueTechOrder(qnTech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        msg = "Empire has many researchers, so attempted to fast-track %s (got result %d) on turn %d" % (
                            qnTech, res, fo.currentTurn())
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()

    #
    # if we own a blackhole, accelerate sing_gen and conc camp
    if True:  # just to help with cold-folding / organization
        if (fo.currentTurn() > 50 and
                len(AIstate.empireStars.get(fo.starType.blackHole, [])) != 0
                and foAI.foAIstate.aggression > fo.aggression.cautious
                and not tech_is_complete(AIDependencies.PRO_SINGULAR_GEN)
                and tech_is_complete(AIDependencies.PRO_SOL_ORB_GEN)):
            # sing_tech_list = [ "LRN_GRAVITONICS" , "PRO_SINGULAR_GEN"]  # formerly also "CON_ARCH_PSYCH", "CON_CONC_CAMP",
            sing_gen_tech = fo.getTech(AIDependencies.PRO_SINGULAR_GEN)
            sing_tech_list = [
                pre_req
                for pre_req in sing_gen_tech.recursivePrerequisites(empire_id)
                if not tech_is_complete(pre_req)
            ]
            sing_tech_list += [AIDependencies.PRO_SINGULAR_GEN]
            for singTech in sing_tech_list:
                if singTech not in research_queue_list[:num_techs_accelerated +
                                                       1]:
                    res = fo.issueEnqueueTechOrder(singTech,
                                                   num_techs_accelerated)
                    num_techs_accelerated += 1
                    msg = "have a black hole star outpost/colony, so attempted to fast-track %s, got result %d" % (
                        singTech, res)
                    print msg
                    if report_adjustments:
                        chat_human(msg)
            research_queue_list = get_research_queue_techs()

    #
    # if got deathray from Ruins, remove most prereqs from queue
    if True:  # just to help with cold-folding / organization
        if tech_is_complete("SHP_WEAPON_4_1"):
            this_tech = fo.getTech("SHP_WEAPON_4_1")
            if this_tech:
                missing_prereqs = [
                    preReq
                    for preReq in this_tech.recursivePrerequisites(empire_id)
                    if preReq in research_queue_list
                ]
                if len(missing_prereqs
                       ) > 2:  # leave plasma 4 and 3 if up to them already
                    for preReq in missing_prereqs:  # sorted(missing_prereqs, reverse=True)[2:]
                        if preReq in research_queue_list:
                            fo.issueDequeueTechOrder(preReq)
                    research_queue_list = get_research_queue_techs()
                    if "SHP_WEAPON_4_2" in research_queue_list:  # (should be)
                        idx = research_queue_list.index("SHP_WEAPON_4_2")
                        fo.issueEnqueueTechOrder("SHP_WEAPON_4_2",
                                                 max(0, idx - 18))
示例#41
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:
        debug("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=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)
    aistate = get_aistate()
    system_status = aistate.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 = aistate.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 in [MissionType.SECURE, MissionType.MILITARY]:
            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:
        debug("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:
        debug(' - 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)
        debug(' - system secured: %s' % system_secured)
    return [planet_score, planned_troops]
示例#42
0
def evaluateInvasionPlanet(planetID, missionType, fleetSupplyablePlanetIDs, empire):
    "return the invasion value of a planet"
    buildingValues = {"BLD_IMPERIAL_PALACE":                    1000, 
                                            "BLD_CULTURE_ARCHIVES":                 1000, 
                                            "BLD_SHIPYARD_BASE":                        100, 
                                            "BLD_SHIPYARD_ORG_ORB_INC":     200, 
                                            "BLD_SHIPYARD_ORG_XENO_FAC": 200, 
                                            "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200, 
                                            "BLD_SHIPYARD_CON_NANOROBO": 300, 
                                            "BLD_SHIPYARD_CON_GEOINT":      400, 
                                            "BLD_SHIPYARD_CON_ADV_ENGINE": 1000, 
                                            "BLD_SHIPYARD_AST":                             150, 
                                            "BLD_SHIPYARD_AST_REF":                     500, 
                                            "BLD_SHIPYARD_ENRG_COMP":           500, 
                                            "BLD_SHIPYARD_ENRG_SOLAR":          1500, 
                                            "BLD_INDUSTRY_CENTER":                   500, 
                                            "BLD_GAS_GIANT_GEN":                           200, 
                                            "BLD_SOL_ORB_GEN":                              800, 
                                            "BLD_BLACK_HOLE_POW_GEN":       2000, 
                                            "BLD_ENCLAVE_VOID":                             500, 
                                            "BLD_NEUTRONIUM_EXTRACTOR": 2000, 
                                            "BLD_NEUTRONIUM_SYNTH":             2000, 
                                            "BLD_NEUTRONIUM_FORGE":             1000, 
                                            "BLD_CONC_CAMP":                                    100, 
                                            "BLD_BIOTERROR_PROJECTOR":      1000, 
                                            "BLD_SHIPYARD_ENRG_COMP":         3000, 
                                            }
    #TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empireID = empire.empireID
    maxJumps=8
    planet = universe.getPlanet(planetID)
    if (planet == None) :  #TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't get current info on planet %d"%planetID
        return 0, 0
        
    bldTally=0
    for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]:
        bldTally += buildingValues.get(bldType,  50)
        
        capitolID = PlanetUtilsAI.getCapital()
        if capitolID:
            homeworld = universe.getPlanet(capitolID)
            if homeworld:
                homeSystemID = homeworld.systemID
                evalSystemID = planet.systemID
                leastJumpsPath = len(universe.leastJumpsPath(homeSystemID, evalSystemID, empireID))
            maxJumps =  leastJumpsPath
        
    troops = planet.currentMeterValue(fo.meterType.troops)
    maxTroops = planet.currentMeterValue(fo.meterType.maxTroops)
    specName=planet.speciesName
    species=fo.getSpecies(specName)
    popTSize = planet.currentMeterValue(fo.meterType.targetPopulation)#TODO: adjust for empire tech
    planetSpecials = list(planet.specials)
    pSysID = planet.systemID#TODO: check star value
    
    indVal = 0
    basePopInd=0.2
    prodFactor = 1
    discountMultiplier=20
    for special in [ "MINERALS_SPECIAL",  "CRYSTALS_SPECIAL",  "METALOIDS_SPECIAL"] : 
        if special in planetSpecials:
            prodFactor+=1
    
    proSingVal = [0, 4][(len( AIstate.empireStars.get(fo.starType.blackHole,  [])) > 0)]
    indTechMap={    "GRO_ENERGY_META":  0.5, 
                                        "PRO_ROBOTIC_PROD":0.4, 
                                        "PRO_FUSION_GEN":       1.0, 
                                        "PRO_INDUSTRY_CENTER_I": 1, 
                                        "PRO_INDUSTRY_CENTER_II":1, 
                                        "PRO_INDUSTRY_CENTER_III":1, 
                                        "PRO_SOL_ORB_GEN":  2.0,   #assumes will build a gen at a blue/white star
                                        "PRO_SINGULAR_GEN": proSingVal, 
                                        }
    for tech in indTechMap:
        if (empire.getTechStatus(tech) == fo.techStatus.complete):
            prodFactor +=  indTechMap[tech]
    indVal = discountMultiplier * basePopInd *prodFactor*popTSize
    if (empire.getTechStatus("PRO_SENTIENT_AUTOMATION") == fo.techStatus.complete):
        indVal += discountMultiplier * 5
    
    pmaxShield = planet.currentMeterValue(fo.meterType.maxShield)
    sysFThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('fleetThreat', 1000 )
    sysMThrt = foAI.foAIstate.systemStatus.get(pSysID, {}).get('monsterThreat', 0 )
    print "invasion eval of %s  %d --- maxShields %.1f -- sysFleetThreat %.1f  -- sysMonsterThreat %.1f"%(planet.name,  planetID,  pmaxShield,  sysFThrt,  sysMThrt)
    supplyVal=0
    enemyVal=0
    if planet.owner!=-1 : #value in taking this away from an enemy
        enemyVal= 20* max(planet.currentMeterValue(fo.meterType.targetIndustry),  2*planet.currentMeterValue(fo.meterType.targetResearch))
    if not species:#TODO:  perhaps stealth makes planet inacccesible & should abort
        try:
            targetPop=planet.currentMeterValue(fo.meterType.targetPopulation)
            popVal =  2*targetPop
        except:
            popVal=0
    else:
        popVal = evaluatePlanet(planetID,  AIFleetMissionType.FLEET_MISSION_COLONISATION,  [planetID],  species,  empire) #evaluatePlanet is imported from ColonisationAI
    if planetID  in fleetSupplyablePlanetIDs: #TODO: extend to rings
        supplyVal =  100
        if planet.owner== -1:
        #if  (pmaxShield <10):
            if ( sysFThrt < 0.5*curBestMilShipRating() ):
               if ( sysMThrt < 3*curBestMilShipRating()):
                    supplyVal = 10000
               else:
                    supplyVal = 50
    planetSpecials = list(planet.specials)
    specialVal=0
    if  ( ( planet.size  ==  fo.planetSize.asteroids ) and  (empire.getTechStatus("PRO_ASTEROID_MINE") == fo.techStatus.complete ) ): 
            specialVal= 15   #TODO: should do more eval re asteroid mining here
    for special in [ "MINERALS_SPECIAL",  "CRYSTALS_SPECIAL",  "METALOIDS_SPECIAL"] :
        if special in planetSpecials:
            specialVal +=10 #
    buildTime=4
    return max(0,  popVal+supplyVal+specialVal+bldTally+indVal+enemyVal-20*troops),  min(troops+maxJumps+buildTime,  maxTroops)
示例#43
0
def generateResearchOrders():
    global inProgressTechs
    "generate research orders"
    
    universe=fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    print "Research Queue Management:"
    tRP = empire.resourceProduction(fo.resourceType.research)
    print "\nTotal Current Research Points: %.2f\n"%tRP
    print "Techs researched and available for use:"
    completedTechs = sorted(list(getCompletedTechs()))
    tlist = completedTechs+3*[" "]
    tlines = zip( tlist[0::3],  tlist[1::3],  tlist[2::3])
    for tline in tlines:
        print "%25s  %25s  %25s"%tline
    print""
    
    researchQueueList = getResearchQueueTechs()
    if tRP >= 20  and foAI.foAIstate.aggression > fo.aggression.cautious:
        if (empire.getTechStatus("LRN_PSIONICS") != fo.techStatus.complete)  and ( "LRN_PSIONICS" not in researchQueueList[:5]  )  :
            for specName in ColonisationAI.empireSpecies:
                thisSpec=fo.getSpecies(specName)
                if thisSpec:
                    if "TELEPATHIC" in list(thisSpec.tags):
                        res=fo.issueEnqueueTechOrder("LRN_DISTRIB_THOUGHT", 0)
                        res=fo.issueEnqueueTechOrder("LRN_PSIONICS", 0)
                        break

    if len(foAI.foAIstate.colonisablePlanetIDs)==0:
        bestColonySiteScore = 0
    else:
        bestColonySiteScore= foAI.foAIstate.colonisablePlanetIDs[0][1]
    if len(foAI.foAIstate.colonisableOutpostIDs)==0:
        bestOutpostSiteScore = 0
    else:
        bestOutpostSiteScore= foAI.foAIstate.colonisableOutpostIDs[0][1]
    needImprovedScouting = ( bestColonySiteScore <150  or   bestOutpostSiteScore < 200 )

    if needImprovedScouting:
        if (empire.getTechStatus("CON_ORBITAL_CON") != fo.techStatus.complete):
            if  ( "CON_ORBITAL_CON" not in researchQueueList[:2]  ) and  ((empire.getTechStatus("PRO_FUSION_GEN") == fo.techStatus.complete) or ( "PRO_FUSION_GEN"  in researchQueueList[:1]  )):
                res=fo.issueEnqueueTechOrder("CON_ORBITAL_CON", 1)
                print "Empire has poor colony/outpost prospects,  so attempted to fast-track %s,  got result %d"%("CON_ORBITAL_CON", res)
        else:
            pass
            #could add more supply tech
        if (empire.getTechStatus("SPY_DETECT_2") != fo.techStatus.complete):
            if  ( "SPY_DETECT_2" not in researchQueueList[:3]  ) and  (empire.getTechStatus("PRO_FUSION_GEN") == fo.techStatus.complete) :
                if  ( "CON_ORBITAL_CON" not in researchQueueList[:2]  ):
                    res=fo.issueEnqueueTechOrder("SPY_DETECT_2", 1)
                else:
                    CO_idx = researchQueueList.index( "CON_ORBITAL_CON")
                    res=fo.issueEnqueueTechOrder("SPY_DETECT_2", CO_idx+1)
                print "Empire has poor colony/outpost prospects,  so attempted to fast-track %s,  got result %d"%("CON_ORBITAL_CON", res)
        
    gotGGG = empire.getTechStatus("PRO_ORBITAL_GEN") == fo.techStatus.complete
    gotSymBio = empire.getTechStatus("GRO_SYMBIOTIC_BIO") == fo.techStatus.complete
    gotXenoGen = empire.getTechStatus("GRO_XENO_GENETICS") == fo.techStatus.complete
    #assess if our empire has any non-lousy colonizers, & boost gro_xeno_gen if we don't
    if gotGGG and gotSymBio and (not gotXenoGen) and foAI.foAIstate.aggression >= fo.aggression.cautious:
        mostAdequate=0
        for specName in ColonisationAI.empireColonizers:
            environs={}
            thisSpec = fo.getSpecies(specName)
            if not thisSpec: continue
            for ptype in [fo.planetType.swamp,  fo.planetType.radiated,  fo.planetType.toxic,  fo.planetType.inferno,  fo.planetType.barren,  fo.planetType.tundra,  fo.planetType.desert,  fo.planetType.terran,  fo.planetType.ocean,  fo.planetType.asteroids]:
                environ=thisSpec.getPlanetEnvironment(ptype)
                environs.setdefault(environ, []).append(ptype)
            mostAdequate = max(mostAdequate,  len(environs.get( fo.planetEnvironment.adequate, [])))
            if mostAdequate==0:
                researchQueue = empire.researchQueue
                researchQueueList = getResearchQueueTechs()
                for xgTech in [ "GRO_XENO_GENETICS", "GRO_GENETIC_ENG" ]:
                    if   xgTech not in researchQueueList[:2]  and  empire.getTechStatus(xgTech) != fo.techStatus.complete:
                        res=fo.issueEnqueueTechOrder(xgTech, 0)
                        print "Empire has poor colonizers,  so attempted to fast-track %s,  got result %d"%(xgTech, res)
    
    researchQueue = empire.researchQueue
    researchQueueList = getResearchQueueTechs()
    inProgressTechs.clear()
    if  researchQueueList:
        print "Techs currently at head of Research Queue:"
        for element in list(researchQueue)[:10]:
            if element.allocation > 0.0:
                inProgressTechs[element.tech]=True
            thisTech=fo.getTech(element.tech)
            missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq not in completedTechs]
            unlockedItems = [(uli.name,  uli.type) for uli in thisTech.unlockedItems]
            if not missingPrereqs:
                print "    %25s  allocated %6.2f RP -- unlockable items: %s "%(element.tech,  element.allocation,  unlockedItems)
            else:
                print "    %25s  allocated %6.2f RP   --  missing preReqs: %s   -- unlockable items: %s "%(element.tech,  element.allocation,  missingPrereqs,  unlockedItems)
        print ""
    if (fo.currentTurn()==1) or ((fo.currentTurn()<5) and (len(researchQueueList)==0) ):
        if foAI.foAIstate.aggression <=fo.aggression.typical:
            newtech = TechsListsAI.primaryMetaTechsList( index=empireID%2 )
        else:
            newtech = TechsListsAI.primaryMetaTechsList( index=empireID%2 )
        #pLTsToEnqueue = (set(newtech)-(set(completedTechs)|set(researchQueueList)))
        pLTsToEnqueue = newtech[:]
        techBase = set(completedTechs+researchQueueList)
        techsToAdd=[]
        for tech in pLTsToEnqueue:
            if (tech not in  techBase): 
                thisTech=fo.getTech(tech)
                if thisTech is None:
                    print "Error: desired tech '%s' appears to not exist"%tech
                    continue
                missingPrereqs = [preReq for preReq in thisTech.recursivePrerequisites(empireID) if preReq not in techBase] 
                techsToAdd.extend( missingPrereqs+[tech] )
                techBase.update(  missingPrereqs+[tech]  )
        cumCost=0
        print "  Enqueued Tech:  %20s \t\t %8s \t %s"%("Name",  "Cost",  "CumulativeCost")
        for name in techsToAdd:
            try:
                enqueueRes = fo.issueEnqueueTechOrder(name, -1)
                if enqueueRes == 1:
                    thisTech=fo.getTech(name)
                    thisCost=0
                    if thisTech:
                        thisCost = thisTech.researchCost(empireID)
                        cumCost += thisCost
                    print "    Enqueued Tech: %20s \t\t %8.0f \t %8.0f" % ( name,  thisCost,  cumCost)
                else:
                    print "    Error: failed attempt to enqueued Tech: " + name
            except:
                print "    Error: failed attempt to enqueued Tech: " + name
                print "    Error: exception triggered and caught:  ",  traceback.format_exc()
        if foAI.foAIstate.aggression <= fo.aggression.cautious:
            researchQueueList = getResearchQueueTechs()
            defTechs=TechsListsAI.defenseTechs1()
            for defTech in defTechs:
                if   defTech not in researchQueueList[:5]  and  empire.getTechStatus(defTech) != fo.techStatus.complete:
                    res=fo.issueEnqueueTechOrder(defTech, min(3,  len(researchQueueList)))
                    print "Empire is very defensive,  so attempted to fast-track %s,  got result %d"%(defTech, res)
        if foAI.foAIstate.aggression >= fo.aggression.aggressive:
            researchQueueList = getResearchQueueTechs()
            if "CON_CONC_CAMP" in researchQueueList:
                insertIdx = min(40,  researchQueueList.index("CON_CONC_CAMP"))
            else:
                insertIdx=max(0,  min(40, len(researchQueueList)-10))
            if "SHP_ASTEROID_HULLS" in researchQueueList:
                insertIdx = min(insertIdx,  researchQueueList.index("SHP_ASTEROID_HULLS"))
            for ccTech in [  "CON_ARCH_PSYCH",  "CON_CONC_CAMP"]:
                if   ccTech not in researchQueueList[:insertIdx+1]  and  empire.getTechStatus(ccTech) != fo.techStatus.complete:
                    res=fo.issueEnqueueTechOrder(ccTech, insertIdx)
                    print "Empire is very aggressive,  so attempted to fast-track %s,  got result %d"%(ccTech, res)
        print""
        
        generateDefaultResearchOrders()
        print "\n\nAll techs:"
        alltechs = fo.techs() # returns names of all techs
        for tname in alltechs:
            print tname
        print "\n-------------------------------\nAll unqueued techs:"
        #coveredTechs = newtech+completedTechs
        for tname in [tn for tn in alltechs if tn not in techBase]:
            print tname

    elif fo.currentTurn() >100:
        generateDefaultResearchOrders()
        
    #researchQueueList = getResearchQueueTechs()
    if fo.currentTurn() >50 and len (AIstate.empireStars.get(fo.starType.blackHole,  []))!=0 and foAI.foAIstate.aggression > fo.aggression.cautious:
        for singTech in [  "CON_ARCH_PSYCH",  "CON_CONC_CAMP",  "LRN_GRAVITONICS" ,  "PRO_SINGULAR_GEN"]:
            if (empire.getTechStatus(singTech) != fo.techStatus.complete) and (  singTech  not in researchQueueList[:4])  :    
                res=fo.issueEnqueueTechOrder(singTech,0)
                print "have a black hole star outpost/colony, so attempted to fast-track %s,  got result %d"%(singTech, res)
示例#44
0
def generate_research_orders():
    """generate research orders"""
    report_adjustments = False
    empire = fo.getEmpire()
    empire_id = empire.empireID
    enemies_sighted = foAI.foAIstate.misc.get('enemies_sighted', {})
    galaxy_is_sparse = ColonisationAI.galaxy_is_sparse()
    print "Research Queue Management:"
    resource_production = empire.resourceProduction(fo.resourceType.research)
    print "\nTotal Current Research Points: %.2f\n" % resource_production
    print "Techs researched and available for use:"
    completed_techs = sorted(list(get_completed_techs()))
    tlist = completed_techs+3*[" "]
    tlines = zip(tlist[0::3], tlist[1::3], tlist[2::3])
    for tline in tlines:
        print "%25s %25s %25s" % tline
    print
    
    #
    # report techs currently at head of research queue
    #
    research_queue = empire.researchQueue
    research_queue_list = get_research_queue_techs()
    inProgressTechs.clear()
    tech_turns_left = {}
    if research_queue_list:
        print "Techs currently at head of Research Queue:"
        for element in list(research_queue)[:10]:
            tech_turns_left[element.tech] = element.turnsLeft
            if element.allocation > 0.0:
                inProgressTechs[element.tech] = True
            this_tech = fo.getTech(element.tech)
            if not this_tech:
                print "Error: can't retrieve tech ", element.tech
                continue
            missing_prereqs = [preReq for preReq in this_tech.recursivePrerequisites(empire_id) if preReq not in completed_techs]
            # unlocked_items = [(uli.name, uli.type) for uli in this_tech.unlocked_items]
            unlocked_items = [uli.name for uli in this_tech.unlockedItems]
            if not missing_prereqs:
                print "    %25s allocated %6.2f RP -- unlockable items: %s " % (element.tech, element.allocation, unlocked_items)
            else:
                print "    %25s allocated %6.2f RP -- missing preReqs: %s -- unlockable items: %s " % (element.tech, element.allocation, missing_prereqs, unlocked_items)
        print
    #
    # set starting techs, or after turn 100 add any additional default techs
    #
    if (fo.currentTurn() == 1) or ((fo.currentTurn() < 5) and (len(research_queue_list) == 0)):
        research_index = get_research_index()
        new_tech = TechsListsAI.sparse_galaxy_techs(research_index) if galaxy_is_sparse else TechsListsAI.primary_meta_techs(research_index)
        print "Empire %s (%d) is selecting research index %d" % (empire.name, empire_id, research_index)
        # techs_to_enqueue = (set(new_tech)-(set(completed_techs)|set(research_queue_list)))
        techs_to_enqueue = new_tech[:]
        tech_base = set(completed_techs+research_queue_list)
        techs_to_add = []
        for tech in techs_to_enqueue:
            if tech not in tech_base:
                this_tech = fo.getTech(tech)
                if this_tech is None:
                    print "Error: desired tech '%s' appears to not exist" % tech
                    continue
                missing_prereqs = [preReq for preReq in this_tech.recursivePrerequisites(empire_id) if preReq not in tech_base]
                techs_to_add.extend(missing_prereqs + [tech])
                tech_base.update(missing_prereqs+[tech])
        cum_cost = 0
        print "  Enqueued Tech: %20s \t\t %8s \t %s" % ("Name", "Cost", "CumulativeCost")
        for name in techs_to_add:
            try:
                enqueue_res = fo.issueEnqueueTechOrder(name, -1)
                if enqueue_res == 1:
                    this_tech = fo.getTech(name)
                    this_cost = 0
                    if this_tech:
                        this_cost = this_tech.researchCost(empire_id)
                        cum_cost += this_cost
                    print "    Enqueued Tech: %20s \t\t %8.0f \t %8.0f" % (name, this_cost, cum_cost)
                else:
                    print "    Error: failed attempt to enqueued Tech: " + name
            except:
                print "    Error: failed attempt to enqueued Tech: " + name
                print "    Error: exception triggered and caught: ", traceback.format_exc()
        if foAI.foAIstate.aggression <= fo.aggression.cautious:
            research_queue_list = get_research_queue_techs()
            def_techs = TechsListsAI.defense_techs_1()
            for def_tech in def_techs:
                if def_tech not in research_queue_list[:5] and not tech_is_complete(def_tech):
                    res = fo.issueEnqueueTechOrder(def_tech, min(3, len(research_queue_list)))
                    print "Empire is very defensive, so attempted to fast-track %s, got result %d" % (def_tech, res)
        if False and foAI.foAIstate.aggression >= fo.aggression.aggressive:  # with current stats of Conc Camps, disabling this fast-track
            research_queue_list = get_research_queue_techs()
            if "CON_CONC_CAMP" in research_queue_list:
                insert_idx = min(40, research_queue_list.index("CON_CONC_CAMP"))
            else:
                insert_idx = max(0, min(40, len(research_queue_list)-10))
            if "SHP_DEFLECTOR_SHIELD" in research_queue_list:
                insert_idx = min(insert_idx, research_queue_list.index("SHP_DEFLECTOR_SHIELD"))
            for cc_tech in ["CON_ARCH_PSYCH", "CON_CONC_CAMP"]:
                if cc_tech not in research_queue_list[:insert_idx + 1] and not tech_is_complete(cc_tech):
                    res = fo.issueEnqueueTechOrder(cc_tech, insert_idx)
                    msg = "Empire is very aggressive, so attempted to fast-track %s, got result %d" % (cc_tech, res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg

        print""

        generate_default_research_order()
        print "\n\nAll techs:"
        alltechs = fo.techs()  # returns names of all techs
        for tname in alltechs:
            print tname
        print "\n-------------------------------\nAll unqueued techs:"
        # coveredTechs = new_tech+completed_techs
        for tname in [tn for tn in alltechs if tn not in tech_base]:
            print tname

    elif fo.currentTurn() > 100:
        generate_default_research_order()

    research_queue_list = get_research_queue_techs()
    num_techs_accelerated = 1  # will ensure leading tech doesn't get dislodged
    got_ggg_tech = tech_is_complete("PRO_ORBITAL_GEN")
    got_sym_bio = tech_is_complete("GRO_SYMBIOTIC_BIO")
    got_xeno_gen = tech_is_complete("GRO_XENO_GENETICS")
    #
    # Consider accelerating techs; priority is
    # Supply/Detect range
    # xeno arch
    # ast / GG
    # gro xeno gen
    # distrib thought
    # quant net
    # pro sing gen
    # death ray 1 cleanup

    #
    # Supply range and detection range
    if False:  # disabled for now, otherwise just to help with cold-folding / organization
        if len(foAI.foAIstate.colonisablePlanetIDs) == 0:
            best_colony_site_score = 0
        else:
            best_colony_site_score = foAI.foAIstate.colonisablePlanetIDs.items()[0][1]
        if len(foAI.foAIstate.colonisableOutpostIDs) == 0:
            best_outpost_site_score = 0
        else:
            best_outpost_site_score = foAI.foAIstate.colonisableOutpostIDs.items()[0][1]
        need_improved_scouting = (best_colony_site_score < 150 or best_outpost_site_score < 200)

        if need_improved_scouting:
            if not tech_is_complete("CON_ORBITAL_CON"):
                num_techs_accelerated += 1
                if ("CON_ORBITAL_CON" not in research_queue_list[:1 + num_techs_accelerated]) and (
                        tech_is_complete("PRO_FUSION_GEN") or ("PRO_FUSION_GEN" in research_queue_list[:1 + num_techs_accelerated])):
                    res = fo.issueEnqueueTechOrder("CON_ORBITAL_CON", num_techs_accelerated)
                    msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % ("CON_ORBITAL_CON", res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
            elif not tech_is_complete("CON_CONTGRAV_ARCH"):
                num_techs_accelerated += 1
                if ("CON_CONTGRAV_ARCH" not in research_queue_list[:1+num_techs_accelerated]) and (
                        tech_is_complete("CON_METRO_INFRA")):
                    for supply_tech in [_s_tech for _s_tech in ["CON_ARCH_MONOFILS", "CON_CONTGRAV_ARCH"] if not tech_is_complete(_s_tech)]:
                        res = fo.issueEnqueueTechOrder(supply_tech, num_techs_accelerated)
                        msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % (supply_tech, res)
                        if report_adjustments:
                            chat_human(msg)
                        else:
                            print msg
            elif not tech_is_complete("CON_GAL_INFRA"):
                num_techs_accelerated += 1
                if ("CON_GAL_INFRA" not in research_queue_list[:1+num_techs_accelerated]) and (
                        tech_is_complete("PRO_SINGULAR_GEN")):
                    res = fo.issueEnqueueTechOrder("CON_GAL_INFRA", num_techs_accelerated)
                    msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % ("CON_GAL_INFRA", res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
            else:
                pass
            research_queue_list = get_research_queue_techs()
            # could add more supply tech

            if False and not tech_is_complete("SPY_DETECT_2"):  # disabled for now, detect2
                num_techs_accelerated += 1
                if "SPY_DETECT_2" not in research_queue_list[:2+num_techs_accelerated] and tech_is_complete("PRO_FUSION_GEN"):
                    if "CON_ORBITAL_CON" not in research_queue_list[:1+num_techs_accelerated]:
                        res = fo.issueEnqueueTechOrder("SPY_DETECT_2", num_techs_accelerated)
                    else:
                        co_idx = research_queue_list.index("CON_ORBITAL_CON")
                        res = fo.issueEnqueueTechOrder("SPY_DETECT_2", co_idx + 1)
                    msg = "Empire has poor colony/outpost prospects, so attempted to fast-track %s, got result %d" % ("CON_ORBITAL_CON", res)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
                research_queue_list = get_research_queue_techs()

    #
    # check to accelerate xeno_arch
    if True:  # just to help with cold-folding /  organization
        if (ColonisationAI.gotRuins and not tech_is_complete("LRN_XENOARCH") and
                foAI.foAIstate.aggression >= fo.aggression.typical):
            if "LRN_ARTIF_MINDS" in research_queue_list:
                insert_idx = 7 + research_queue_list.index("LRN_ARTIF_MINDS")
            elif "GRO_SYMBIOTIC_BIO" in research_queue_list:
                insert_idx = research_queue_list.index("GRO_SYMBIOTIC_BIO") + 1
            else:
                insert_idx = num_techs_accelerated
            if "LRN_XENOARCH" not in research_queue_list[:insert_idx]:
                for xenoTech in ["LRN_XENOARCH", "LRN_TRANSLING_THT", "LRN_PHYS_BRAIN", "LRN_ALGO_ELEGANCE"]:
                    if not tech_is_complete(xenoTech) and xenoTech not in research_queue_list[:(insert_idx + 4)]:
                        res = fo.issueEnqueueTechOrder(xenoTech, insert_idx)
                        num_techs_accelerated += 1
                        msg = "ANCIENT_RUINS: have an ancient ruins, so attempted to fast-track %s to enable LRN_XENOARCH, got result %d" % (xenoTech, res)
                        if report_adjustments:
                            chat_human(msg)
                        else:
                            print msg
                research_queue_list = get_research_queue_techs()

    if False and not enemies_sighted:  # curently disabled
        # params = [ (tech, gate, target_slot, add_tech_list), ]
        params = [("GRO_XENO_GENETICS", "PRO_EXOBOTS", "PRO_EXOBOTS", ["GRO_GENETIC_MED", "GRO_XENO_GENETICS"]),
                  ("PRO_EXOBOTS", "PRO_SENTIENT_AUTOMATION", "PRO_SENTIENT_AUTOMATION", ["PRO_EXOBOTS"]),
                  ("PRO_SENTIENT_AUTOMATION", "PRO_NANOTECH_PROD", "PRO_NANOTECH_PROD", ["PRO_SENTIENT_AUTOMATION"]),
                  ("PRO_INDUSTRY_CENTER_I", "GRO_SYMBIOTIC_BIO", "GRO_SYMBIOTIC_BIO", ["PRO_ROBOTIC_PROD", "PRO_FUSION_GEN", "PRO_INDUSTRY_CENTER_I"]),
                  ("GRO_SYMBIOTIC_BIO", "SHP_ORG_HULL", "SHP_ZORTRIUM_PLATE", ["GRO_SYMBIOTIC_BIO"]),
                  ]
        for (tech, gate, target_slot, add_tech_list) in params:
            if tech_is_complete(tech):
                break
            if tech_turns_left.get(gate, 0) not in [0, 1, 2]:  # needs to exclude -1, the flag for no predicted completion
                continue
            if target_slot in research_queue_list:
                target_index = 1 + research_queue_list.index(target_slot)
            else:
                target_index = num_techs_accelerated
            for move_tech in add_tech_list:
                print "for tech %s, target_slot %s, target_index:%s ; num_techs_accelerated:%s" % (move_tech, target_slot, target_index, num_techs_accelerated)
                if tech_is_complete(move_tech):
                    continue
                if target_index <= num_techs_accelerated:
                    num_techs_accelerated += 1
                if move_tech not in research_queue_list[:1 + target_index]:
                    res = fo.issueEnqueueTechOrder(move_tech, target_index)
                    msg = "Research: To prioritize %s, have advanced %s to slot %d" % (tech, move_tech, target_index)
                    if report_adjustments:
                        chat_human(msg)
                    else:
                        print msg
                    target_index += 1
    #
    # check to accelerate asteroid or GG tech
    if True:  # just to help with cold-folding / organization
        if ColonisationAI.got_ast:
            insert_idx = num_techs_accelerated if "GRO_SYMBIOTIC_BIO" not in research_queue_list else research_queue_list.index("GRO_SYMBIOTIC_BIO")
            ast_tech = "PRO_MICROGRAV_MAN"
            if not (tech_is_complete(ast_tech) or ast_tech in research_queue_list[:(1 + insert_idx)]):
                res = fo.issueEnqueueTechOrder(ast_tech, insert_idx)
                num_techs_accelerated += 1
                msg = "Asteroids: plan to colonize an asteroid belt, so attempted to fast-track %s , got result %d" % (ast_tech, res)
                if report_adjustments:
                    chat_human(msg)
                else:
                    print msg
                research_queue_list = get_research_queue_techs()
            elif tech_is_complete("SHP_ZORTRIUM_PLATE"):
                insert_idx = (1 + insert_idx) if "LRN_FORCE_FIELD" not in research_queue_list else max(1 + insert_idx, research_queue_list.index("LRN_FORCE_FIELD") - 1)
                for ast_tech in ["SHP_ASTEROID_HULLS", "SHP_IMPROVED_ENGINE_COUPLINGS"]:
                    if not tech_is_complete(ast_tech) and ast_tech not in research_queue_list[:insert_idx + 1]:
                        res = fo.issueEnqueueTechOrder(ast_tech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        msg = "Asteroids: plan to colonize an asteroid belt, so attempted to fast-track %s , got result %d" % (ast_tech, res)
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()
        if ColonisationAI.got_gg and not tech_is_complete("PRO_ORBITAL_GEN"):
            fusion_idx = 0 if "PRO_FUSION_GEN" not in research_queue_list else (1 + research_queue_list.index("PRO_FUSION_GEN"))
            forcefields_idx = 0 if "LRN_FORCE_FIELD" not in research_queue_list else (1 + research_queue_list.index("LRN_FORCE_FIELD"))
            insert_idx = max(fusion_idx, forcefields_idx) if enemies_sighted else fusion_idx
            if "PRO_ORBITAL_GEN" not in research_queue_list[:insert_idx+1]:
                res = fo.issueEnqueueTechOrder("PRO_ORBITAL_GEN", insert_idx)
                num_techs_accelerated += 1
                msg = "GasGiant: plan to colonize a gas giant, so attempted to fast-track %s, got result %d" % ("PRO_ORBITAL_GEN", res)
                print msg
                if report_adjustments:
                    chat_human(msg)
                research_queue_list = get_research_queue_techs()
    #
    # assess if our empire has any non-lousy colonizers, & boost gro_xeno_gen if we don't
    if True:  # just to help with cold-folding / organization
        if got_ggg_tech and got_sym_bio and (not got_xeno_gen) and foAI.foAIstate.aggression >= fo.aggression.cautious:
            most_adequate = 0
            for specName in ColonisationAI.empire_colonizers:
                environs = {}
                this_spec = fo.getSpecies(specName)
                if not this_spec:
                    continue
                for ptype in [fo.planetType.swamp, fo.planetType.radiated, fo.planetType.toxic, fo.planetType.inferno, fo.planetType.barren, fo.planetType.tundra, fo.planetType.desert, fo.planetType.terran, fo.planetType.ocean, fo.planetType.asteroids]:
                    environ = this_spec.getPlanetEnvironment(ptype)
                    environs.setdefault(environ, []).append(ptype)
                most_adequate = max(most_adequate, len(environs.get(fo.planetEnvironment.adequate, [])))
            if most_adequate == 0:
                insert_idx = num_techs_accelerated
                for xg_tech in ["GRO_XENO_GENETICS", "GRO_GENETIC_ENG"]:
                    if xg_tech not in research_queue_list[:1+num_techs_accelerated] and not tech_is_complete(xg_tech):
                        res = fo.issueEnqueueTechOrder(xg_tech, insert_idx)
                        num_techs_accelerated += 1
                        msg = "Empire has poor colonizers, so attempted to fast-track %s, got result %d" % (xg_tech, res)
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()
    #
    # check to accelerate distrib thought
    if True:  # just to help with cold-folding / organization
        if not tech_is_complete("LRN_DISTRIB_THOUGHT"):
            got_telepathy = False
            for specName in ColonisationAI.empire_species:
                this_spec = fo.getSpecies(specName)
                if this_spec and ("TELEPATHIC" in list(this_spec.tags)):
                    got_telepathy = True
                    break
            if (foAI.foAIstate.aggression > fo.aggression.cautious) and (empire.population() > ([300, 100][got_telepathy])):
                insert_idx = num_techs_accelerated
                for dt_ech in ["LRN_PHYS_BRAIN", "LRN_TRANSLING_THT", "LRN_PSIONICS", "LRN_DISTRIB_THOUGHT"]:
                    if dt_ech not in research_queue_list[:insert_idx + 2] and not tech_is_complete(dt_ech):
                        res = fo.issueEnqueueTechOrder(dt_ech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        fmt_str = "Empire has a telepathic race, so attempted to fast-track %s (got result %d)"
                        fmt_str += " with current target_RP %.1f and current pop %.1f, on turn %d"
                        msg = fmt_str % (dt_ech, res, resource_production, empire.population(), fo.currentTurn())
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()
    #
    # check to accelerate quant net
    if False:  # disabled for now, otherwise just to help with cold-folding / organization
        if (foAI.foAIstate.aggression > fo.aggression.cautious) and (ColonisationAI.empire_status.get('researchers', 0) >= 40):
            if not tech_is_complete("LRN_QUANT_NET"):
                insert_idx = num_techs_accelerated  # TODO determine min target slot if reenabling
                for qnTech in ["LRN_NDIM_SUBSPACE", "LRN_QUANT_NET"]:
                    if qnTech not in research_queue_list[:insert_idx + 2] and not tech_is_complete(qnTech):
                        res = fo.issueEnqueueTechOrder(qnTech, insert_idx)
                        num_techs_accelerated += 1
                        insert_idx += 1
                        msg = "Empire has many researchers, so attempted to fast-track %s (got result %d) on turn %d" % (qnTech, res, fo.currentTurn())
                        print msg
                        if report_adjustments:
                            chat_human(msg)
                research_queue_list = get_research_queue_techs()

    #
    # if we own a blackhole, accelerate sing_gen and conc camp
    if True:  # just to help with cold-folding / organization
        if (fo.currentTurn() > 50 and len(AIstate.empireStars.get(fo.starType.blackHole, [])) != 0 and
                foAI.foAIstate.aggression > fo.aggression.cautious and not tech_is_complete(AIDependencies.PRO_SINGULAR_GEN) and
                tech_is_complete(AIDependencies.PRO_SOL_ORB_GEN)):
            # sing_tech_list = [ "LRN_GRAVITONICS" , "PRO_SINGULAR_GEN"]  # formerly also "CON_ARCH_PSYCH", "CON_CONC_CAMP",
            sing_gen_tech = fo.getTech(AIDependencies.PRO_SINGULAR_GEN)
            sing_tech_list = [pre_req for pre_req in sing_gen_tech.recursivePrerequisites(empire_id) if not tech_is_complete(pre_req)]
            sing_tech_list += [AIDependencies.PRO_SINGULAR_GEN]
            for singTech in sing_tech_list:
                if singTech not in research_queue_list[:num_techs_accelerated+1]:
                    res = fo.issueEnqueueTechOrder(singTech, num_techs_accelerated)
                    num_techs_accelerated += 1
                    msg = "have a black hole star outpost/colony, so attempted to fast-track %s, got result %d" % (singTech, res)
                    print msg
                    if report_adjustments:
                        chat_human(msg)
            research_queue_list = get_research_queue_techs()

    #
    # if got deathray from Ruins, remove most prereqs from queue
    if True:  # just to help with cold-folding / organization
        if tech_is_complete("SHP_WEAPON_4_1"):
            this_tech = fo.getTech("SHP_WEAPON_4_1")
            if this_tech:
                missing_prereqs = [preReq for preReq in this_tech.recursivePrerequisites(empire_id) if preReq in research_queue_list]
                if len(missing_prereqs) > 2:  # leave plasma 4 and 3 if up to them already
                    for preReq in missing_prereqs:  # sorted(missing_prereqs, reverse=True)[2:]
                        if preReq in research_queue_list:
                            fo.issueDequeueTechOrder(preReq)
                    research_queue_list = get_research_queue_techs()
                    if "SHP_WEAPON_4_2" in research_queue_list:  # (should be)
                        idx = research_queue_list.index("SHP_WEAPON_4_2")
                        fo.issueEnqueueTechOrder("SHP_WEAPON_4_2", max(0, idx-18))
示例#45
0
def evaluate_invasion_planet(planet_id, secure_fleet_missions, verbose=True):
    """Return the invasion value (score, troops) of a planet."""
    detail = []
    building_values = {"BLD_IMPERIAL_PALACE": 1000,
                       "BLD_CULTURE_ARCHIVES": 1000,
                       "BLD_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,
                       }
    # TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    max_jumps = 8
    planet = universe.getPlanet(planet_id)
    if planet is None:  # TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't access any info for planet id %d" % planet_id
        return [0, 0]

    sys_partial_vis_turn = universe.getVisibilityTurnsMap(planet.systemID, empire_id).get(fo.visibility.partial, -9999)
    planet_partial_vis_turn = universe.getVisibilityTurnsMap(planet_id, empire_id).get(fo.visibility.partial, -9999)

    if planet_partial_vis_turn < sys_partial_vis_turn:
        print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id
        # TODO: track detection strength, order new scouting when it goes up
        return [0, 0]  # last time we had partial vis of the system, the planet was stealthed to us

    species_name = planet.speciesName
    species = fo.getSpecies(species_name)
    if not species 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)
        pop_val = max(0.75 * planet_eval.get(planet_id, [0])[0],
                      ColonisationAI.evaluate_planet(planet_id, MissionType.OUTPOST, None, detail))
    else:
        pop_val = ColonisationAI.evaluate_planet(planet_id, MissionType.INVASION, species_name, detail)

    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))

    tech_tally = 0
    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_tally += rp_cost * 4
            detail.append("%s: %d" % (unlocked_tech, rp_cost * 4))

    p_sys_id = planet.systemID
    capitol_id = PlanetUtilsAI.get_capital()
    least_jumps_path = []
    clear_path = True
    if capitol_id:
        homeworld = universe.getPlanet(capitol_id)
        if homeworld:
            home_system_id = homeworld.systemID
            eval_system_id = planet.systemID
            if (home_system_id != INVALID_ID) and (eval_system_id != INVALID_ID):
                least_jumps_path = list(universe.leastJumpsPath(home_system_id, eval_system_id, empire_id))
                max_jumps = len(least_jumps_path)
    system_status = foAI.foAIstate.systemStatus.get(p_sys_id, {})
    system_fleet_treat = system_status.get('fleetThreat', 1000)
    system_monster_threat = system_status.get('monsterThreat', 0)
    sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get('planetThreat', 0)
    max_path_threat = system_fleet_treat
    mil_ship_rating = 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)
    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(p_sys_id)
    secure_targets = [p_sys_id] + list(this_system.planetIDs)
    system_secured = False
    for mission in secure_fleet_missions:
        if system_secured:
            break
        secure_fleet_id = mission.fleet.id
        s_fleet = universe.getFleet(secure_fleet_id)
        if not s_fleet or s_fleet.systemID != p_sys_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)
    supply_val = 0
    enemy_val = 0
    if planet.owner != -1:  # value in taking this away from an enemy
        enemy_val = 20 * (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch))
    if p_sys_id in ColonisationAI.annexable_system_ids:  # TODO: extend to rings
        supply_val = 100
    elif p_sys_id in ColonisationAI.annexable_ring1:
        supply_val = 200
    elif p_sys_id in ColonisationAI.annexable_ring2:
        supply_val = 300
    elif p_sys_id in ColonisationAI.annexable_ring3:
        supply_val = 400
    if max_path_threat > 0.5 * mil_ship_rating:
        if max_path_threat < 3 * mil_ship_rating:
            supply_val *= 0.5
        else:
            supply_val *= 0.2

    threat_factor = min(1, 0.2*MilitaryAI.get_tot_mil_rating()/(sys_total_threat+0.001))**2  # devalue invasions that would require too much military force

    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 + 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 + 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 = pop_val + supply_val + bld_tally + tech_tally + enemy_val - cost_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'
               ' - troop score: %.2f\n'
               ' - projected troop cost: %.1f\n'
               ' - threat factor: %s\n'
               ' - planet detail: %s\n'
               ' - popval: %.1f\n'
               ' - supplyval: %.1f\n'
               ' - bldval: %s\n'
               ' - enemyval: %s') % (planet_score, planned_troops, troop_cost,
                                     threat_factor, detail, pop_val, supply_val, bld_tally, enemy_val)
    return [planet_score, planned_troops]
示例#46
0
def evaluate_invasion_planet(planet_id, empire, secure_fleet_missions, verbose=True):
    """Return the invasion value (score, troops) of a planet."""
    detail = []
    building_values = {"BLD_IMPERIAL_PALACE": 1000,
                       "BLD_CULTURE_ARCHIVES": 1000,
                       "BLD_SHIPYARD_BASE": 100,
                       "BLD_SHIPYARD_ORG_ORB_INC": 200,
                       "BLD_SHIPYARD_ORG_XENO_FAC": 200,
                       "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200,
                       "BLD_SHIPYARD_CON_NANOROBO": 300,
                       "BLD_SHIPYARD_CON_GEOINT": 400,
                       "BLD_SHIPYARD_CON_ADV_ENGINE": 1000,
                       "BLD_SHIPYARD_AST": 300,
                       "BLD_SHIPYARD_AST_REF": 1000,
                       "BLD_SHIPYARD_ENRG_SOLAR": 1500,
                       "BLD_INDUSTRY_CENTER": 500,
                       "BLD_GAS_GIANT_GEN": 200,
                       "BLD_SOL_ORB_GEN": 800,
                       "BLD_BLACK_HOLE_POW_GEN": 2000,
                       "BLD_ENCLAVE_VOID": 500,
                       "BLD_NEUTRONIUM_EXTRACTOR": 2000,
                       "BLD_NEUTRONIUM_SYNTH": 2000,
                       "BLD_NEUTRONIUM_FORGE": 1000,
                       "BLD_CONC_CAMP": 100,
                       "BLD_BIOTERROR_PROJECTOR": 1000,
                       "BLD_SHIPYARD_ENRG_COMP": 3000,
                       }
    # TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empire_id = empire.empireID
    max_jumps = 8
    planet = universe.getPlanet(planet_id)
    if planet is None:  # TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't access any info for planet id %d" % planet_id
        return [0, 0]

    sys_partial_vis_turn = universe.getVisibilityTurnsMap(planet.systemID, empire_id).get(fo.visibility.partial, -9999)
    planet_partial_vis_turn = universe.getVisibilityTurnsMap(planet_id, empire_id).get(fo.visibility.partial, -9999)

    if planet_partial_vis_turn < sys_partial_vis_turn:
        print "invasion AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id
        # TODO: track detection strength, order new scouting when it goes up
        return [0, 0]  # last time we had partial vis of the system, the planet was stealthed to us

    species_name = planet.speciesName
    species = fo.getSpecies(species_name)
    if not species:  # this call iterates over this Empire's available species with which it could colonize after an invasion
        planet_eval = ColonisationAI.assign_colonisation_values([planet_id], EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, None, empire, detail)
        pop_val = max(0.75*planet_eval.get(planet_id, [0])[0], ColonisationAI.evaluate_planet(planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_OUTPOST, None, empire, detail))
    else:
        pop_val = ColonisationAI.evaluate_planet(planet_id, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, species_name, empire, detail)

    bld_tally = 0
    for bldType in [universe.getObject(bldg).buildingTypeName for bldg in planet.buildingIDs]:
        bval = building_values.get(bldType, 50)
        bld_tally += bval
        detail.append("%s: %d" % (bldType, bval))

    p_sys_id = planet.systemID
    capitol_id = PlanetUtilsAI.get_capital()
    least_jumps_path = []
    clear_path = True
    if capitol_id:
        homeworld = universe.getPlanet(capitol_id)
        if homeworld:
            home_system_id = homeworld.systemID
            eval_system_id = planet.systemID
            if (home_system_id != -1) and (eval_system_id != -1):
                least_jumps_path = list(universe.leastJumpsPath(home_system_id, eval_system_id, empire_id))
                max_jumps = len(least_jumps_path)
    system_status = foAI.foAIstate.systemStatus.get(p_sys_id, {})
    system_fleet_treat = system_status.get('fleetThreat', 1000)
    system_monster_threat = system_status.get('monsterThreat', 0)
    sys_total_threat = system_fleet_treat + system_monster_threat + system_status.get('planetThreat', 0)
    max_path_threat = system_fleet_treat
    mil_ship_rating = 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)
    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(p_sys_id)
    secure_targets = [p_sys_id] + list(this_system.planetIDs)
    system_secured = False
    for mission in secure_fleet_missions:
        if system_secured:
            break
        secure_fleet_id = mission.target_id
        s_fleet = universe.getFleet(secure_fleet_id)
        if not s_fleet or s_fleet.systemID != p_sys_id:
            continue
        for ai_target in mission.get_targets(EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE):
            target_obj = ai_target.target_obj
            if (target_obj is not None) and target_obj.id in secure_targets:
                system_secured = True
                break
    system_secured = system_secured and system_status.get('myFleetRating',0)

    if verbose:
        print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f" % (
            planet.name, planet_id, planet.currentMeterValue(fo.meterType.maxShield), system_fleet_treat,
            system_monster_threat)
    supply_val = 0
    enemy_val = 0
    if planet.owner != -1:  # value in taking this away from an enemy
        enemy_val = 20 * (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch))
    if p_sys_id in ColonisationAI.annexable_system_ids:  # TODO: extend to rings
        supply_val = 100
    elif p_sys_id in ColonisationAI.annexable_ring1:
        supply_val = 200
    elif p_sys_id in ColonisationAI.annexable_ring2:
        supply_val = 300
    elif p_sys_id in ColonisationAI.annexable_ring3:
        supply_val = 400
    if max_path_threat > 0.5 * mil_ship_rating:
        if max_path_threat < 3 * mil_ship_rating:
            supply_val *= 0.5
        else:
            supply_val *= 0.2
        
    threat_factor = min(1, 0.2*MilitaryAI.totMilRating/(sys_total_threat+0.001))**2  # devalue invasions that would require too much military force
    build_time = 4

    planned_troops = troops if system_secured else min(troops+max_jumps+build_time, max_troops)
    if not tech_is_complete("SHP_ORG_HULL"):
        troop_cost = math.ceil(planned_troops/6.0) * (40*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP))
    else:
        troop_cost = math.ceil(planned_troops/6.0) * (20*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP))
    planet_score = retaliation_risk_factor(planet.owner) * threat_factor * max(0, pop_val+supply_val+bld_tally+enemy_val-0.8*troop_cost)
    if clear_path:
        planet_score *= 1.5
    invasion_score = [planet_score, planned_troops]
    print invasion_score, "projected Troop Cost:", troop_cost, ", threatFactor: ", threat_factor, ", planet detail ", detail, "popval, supplyval, bldval, enemyval", pop_val, supply_val, bld_tally, enemy_val
    return invasion_score
示例#47
0
def survey_universe():
    survey_timer.start("Categorizing Visible Planets")
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    current_turn = fo.currentTurn()

    # set up / reset various variables; the 'if' is purely for code folding convenience
    if True:
        AIstate.empireStars.clear()
        empire_metabolisms.clear()
        active_growth_specials.clear()

    # var setup done
    aistate = get_aistate()
    for sys_id in universe.systemIDs:
        system = universe.getSystem(sys_id)
        if not system:
            continue
        local_ast = False
        local_gg = False
        empire_has_qualifying_planet = False
        if sys_id in AIstate.colonyTargetedSystemIDs:
            empire_has_qualifying_planet = True
        for pid in system.planetIDs:
            planet = universe.getPlanet(pid)
            if not planet:
                continue
            if pid in aistate.colonisablePlanetIDs:
                empire_has_qualifying_planet = True
            if planet.size == fo.planetSize.asteroids:
                local_ast = True
            elif planet.size == fo.planetSize.gasGiant:
                local_gg = True
            spec_name = planet.speciesName
            this_spec = fo.getSpecies(spec_name)
            owner_id = planet.owner
            planet_population = planet.currentMeterValue(
                fo.meterType.population)
            buildings_here = [
                universe.getBuilding(bldg).buildingTypeName
                for bldg in planet.buildingIDs
            ]
            weapons_grade = "WEAPONS_0.0"
            if owner_id == empire_id:
                if planet_population > 0.0 and this_spec:
                    empire_has_qualifying_planet = True
                    for metab in [
                            tag for tag in this_spec.tags
                            if tag in AIDependencies.metabolismBoostMap
                    ]:
                        empire_metabolisms[metab] = empire_metabolisms.get(
                            metab, 0.0) + planet.habitableSize
                    if this_spec.canProduceShips:
                        pilot_val = rate_piloting_tag(spec_name)
                        if spec_name == "SP_ACIREMA":
                            pilot_val += 1
                        weapons_grade = "WEAPONS_%.1f" % pilot_val
                        set_pilot_rating_for_planet(pid, pilot_val)
                        yard_here = []
                        if "BLD_SHIPYARD_BASE" in buildings_here:
                            set_ship_builders(spec_name, pid)
                            yard_here = [pid]
                        if this_spec.canColonize and planet.currentMeterValue(
                                fo.meterType.targetPopulation) >= 3:
                            set_colony_builders(spec_name, yard_here)
                set_building_locations(weapons_grade, buildings_here, pid)

                for special in planet.specials:
                    if special_is_nest(special):
                        set_have_nest()
                    if special in AIDependencies.metabolismBoosts:
                        set_growth_special(special, pid)
                        if planet.focus == FocusType.FOCUS_GROWTH:
                            active_growth_specials.setdefault(special,
                                                              []).append(pid)
            elif owner_id != -1:
                if get_partial_visibility_turn(
                        pid
                ) >= current_turn - 1:  # only interested in immediately recent data
                    aistate.misc.setdefault("enemies_sighted",
                                            {}).setdefault(current_turn,
                                                           []).append(pid)

        if empire_has_qualifying_planet:
            if local_ast:
                set_have_asteroids()
            elif local_gg:
                set_have_gas_giant()

        if sys_id in get_owned_planets():
            AIstate.empireStars.setdefault(system.starType, []).append(sys_id)
            sys_status = aistate.systemStatus.setdefault(sys_id, {})
            if sys_status.get("fleetThreat", 0) > 0:
                set_colonies_is_under_attack()
            if sys_status.get("neighborThreat", 0) > 0:
                set_colonies_is_under_treat()

    survey_universe_lock.unlock()
    survey_timer.stop()

    # lock must be released before this, since it uses the locked functions
    _print_empire_species_roster()
示例#48
0
def _calculate_planet_colonization_rating(
    planet_id: PlanetId,
    mission_type: MissionType,
    species_name: SpeciesName,
    detail: list,
    empire_research_list: Sequence,
) -> float:
    empire = fo.getEmpire()
    retval = 0
    character = get_aistate().character
    discount_multiplier = character.preferred_discount_multiplier([30.0, 40.0])
    species = fo.getSpecies(species_name)
    species_foci = [] and species and list(species.foci)
    tag_list = list(species.tags) if species else []
    pilot_val = pilot_rating = 0
    if species and species.canProduceShips:
        pilot_val = pilot_rating = rate_piloting_tag(species_name)
        if pilot_val > best_pilot_rating():
            pilot_val *= 2
        if pilot_val > 2:
            retval += discount_multiplier * 5 * pilot_val
            detail.append("Pilot Val %.1f" %
                          (discount_multiplier * 5 * pilot_val))

    if empire.productionPoints < 100:
        backup_factor = 0.0
    else:
        backup_factor = min(1.0, (empire.productionPoints / 200.0)**2)

    universe = fo.getUniverse()
    capital_id = PlanetUtilsAI.get_capital()
    homeworld = universe.getPlanet(capital_id)
    planet = universe.getPlanet(planet_id)
    prospective_invasion_targets = [
        pid for pid, pscore, trp in
        AIstate.invasionTargets[:PriorityAI.allotted_invasion_targets()]
        if pscore > InvasionAI.MIN_INVASION_SCORE
    ]

    if species_name != planet.speciesName and planet.speciesName and mission_type != MissionType.INVASION:
        return 0

    this_sysid = planet.systemID
    if homeworld:
        home_system_id = homeworld.systemID
        eval_system_id = this_sysid
        if home_system_id != INVALID_ID and eval_system_id != INVALID_ID:
            least_jumps = universe.jumpDistance(home_system_id, eval_system_id)
            if least_jumps == -1:  # indicates no known path
                return 0.0

    if planet is None:
        vis_map = universe.getVisibilityTurnsMap(planet_id, empire.empireID)
        debug("Planet %d object not available; visMap: %s" %
              (planet_id, vis_map))
        return 0
    # only count existing presence if not target planet
    # TODO: consider neighboring sytems for smaller contribution, and bigger contributions for
    # local colonies versus local outposts
    locally_owned_planets = [
        lpid for lpid in get_owned_planets_in_system(this_sysid)
        if lpid != planet_id
    ]
    planets_with_species = get_inhabited_planets()
    locally_owned_pop_ctrs = [
        lpid for lpid in locally_owned_planets if lpid in planets_with_species
    ]
    # triple count pop_ctrs
    existing_presence = len(
        locally_owned_planets) + 2 * len(locally_owned_pop_ctrs)
    system = universe.getSystem(this_sysid)

    sys_supply = get_system_supply(this_sysid)
    planet_supply = AIDependencies.supply_by_size.get(planet.size, 0)
    bld_types = set(
        universe.getBuilding(bldg).buildingTypeName
        for bldg in planet.buildingIDs).intersection(
            AIDependencies.building_supply)
    planet_supply += sum(
        AIDependencies.building_supply[bld_type].get(int(psize), 0)
        for psize in [-1, planet.size] for bld_type in bld_types)

    supply_specials = set(planet.specials).union(system.specials).intersection(
        AIDependencies.SUPPLY_MOD_SPECIALS)
    planet_supply += sum(
        AIDependencies.SUPPLY_MOD_SPECIALS[_special].get(int(psize), 0)
        for _special in supply_specials for psize in [-1, planet.size])

    ind_tag_mod = AIDependencies.SPECIES_INDUSTRY_MODIFIER.get(
        get_species_tag_grade(species_name, Tags.INDUSTRY), 1.0)
    res_tag_mod = AIDependencies.SPECIES_RESEARCH_MODIFIER.get(
        get_species_tag_grade(species_name, Tags.RESEARCH), 1.0)
    if species:
        supply_tag_mod = AIDependencies.SPECIES_SUPPLY_MODIFIER.get(
            get_species_tag_grade(species_name, Tags.SUPPLY), 1)
    else:
        supply_tag_mod = 0

    # determine the potential supply provided by owning this planet, and if the planet is currently populated by
    # the evaluated species, then save this supply value in a cache.
    # The system supply value can be negative (indicates the respective number of starlane jumps to the closest supplied
    # system).  So if this total planet supply value is non-negative, then the planet would be supply connected (to at
    # least a portion of the existing empire) if the planet becomes owned by the AI.

    planet_supply += supply_tag_mod
    planet_supply = max(planet_supply, 0)  # planets can't have negative supply
    if planet.speciesName == species_name:
        update_planet_supply(planet_id, planet_supply + sys_supply)

    threat_factor = _determine_colony_threat_factor(planet_id, species_name,
                                                    existing_presence)

    sys_partial_vis_turn = get_partial_visibility_turn(this_sysid)
    planet_partial_vis_turn = get_partial_visibility_turn(planet_id)

    if planet_partial_vis_turn < sys_partial_vis_turn:
        # last time we had partial vis of the system, the planet was stealthed to us
        # print "Colonization AI couldn't get current info on planet id %d (was stealthed at last sighting)" % planet_id
        return 0  # TODO: track detection strength, order new scouting when it goes up

    star_bonus = 0
    colony_star_bonus = 0
    research_bonus = 0
    growth_val = 0
    fixed_ind = 0
    fixed_res = 0
    if system:
        already_got_this_one = this_sysid in get_owned_planets()
        # TODO: Should probably consider pilot rating also for Phototropic species
        if "PHOTOTROPHIC" not in tag_list and pilot_rating >= best_pilot_rating(
        ):
            if system.starType == fo.starType.red and tech_is_complete(
                    "LRN_STELLAR_TOMOGRAPHY"):
                star_bonus += 40 * discount_multiplier  # can be used for artif'l black hole and solar hull
                detail.append(
                    "Red Star for Art Black Hole for solar hull %.1f" %
                    (40 * discount_multiplier))
            elif system.starType == fo.starType.blackHole and tech_is_complete(
                    "SHP_FRC_ENRG_COMP"):
                star_bonus += 100 * discount_multiplier  # can be used for solar hull
                detail.append("Black Hole for solar hull %.1f" %
                              (100 * discount_multiplier))

        if tech_is_complete("PRO_SOL_ORB_GEN"
                            ) or "PRO_SOL_ORB_GEN" in empire_research_list[:5]:
            if system.starType in [fo.starType.blue, fo.starType.white]:
                if not has_claimed_star(fo.starType.blue, fo.starType.white):
                    star_bonus += 20 * discount_multiplier
                    detail.append("PRO_SOL_ORB_GEN BW %.1f" %
                                  (20 * discount_multiplier))
                elif not already_got_this_one:
                    # still has extra value as an alternate location for solar generators
                    star_bonus += 10 * discount_multiplier * backup_factor
                    detail.append("PRO_SOL_ORB_GEN BW Backup Location %.1f" %
                                  (10 * discount_multiplier * backup_factor))
                elif fo.currentTurn() > 100:  # lock up this whole system
                    pass
                    # starBonus += 5  # TODO: how much?
                    # detail.append("PRO_SOL_ORB_GEN BW LockingDownSystem %.1f"%5)
            if system.starType in [fo.starType.yellow, fo.starType.orange]:
                if not has_claimed_star(fo.starType.blue, fo.starType.white,
                                        fo.starType.yellow,
                                        fo.starType.orange):
                    star_bonus += 10 * discount_multiplier
                    detail.append("PRO_SOL_ORB_GEN YO %.1f" %
                                  (10 * discount_multiplier))
                else:
                    pass
                    # starBonus +=2  # still has extra value as an alternate location for solar generators
                    # detail.append("PRO_SOL_ORB_GEN YO Backup %.1f" % 2)
        if system.starType in [fo.starType.blackHole
                               ] and fo.currentTurn() > 100:
            if not already_got_this_one:
                # whether have tech yet or not, assign some base value
                star_bonus += 10 * discount_multiplier * backup_factor
                detail.append("Black Hole %.1f" %
                              (10 * discount_multiplier * backup_factor))
            else:
                star_bonus += 5 * discount_multiplier * backup_factor
                detail.append("Black Hole Backup %.1f" %
                              (5 * discount_multiplier * backup_factor))
        if tech_is_complete(AIDependencies.PRO_SOL_ORB_GEN
                            ):  # start valuing as soon as PRO_SOL_ORB_GEN done
            if system.starType == fo.starType.blackHole:
                # pretty rare planets, good for generator
                this_val = 0.5 * max(population_with_industry_focus(),
                                     20) * discount_multiplier
                if not has_claimed_star(fo.starType.blackHole):
                    star_bonus += this_val
                    detail.append("PRO_SINGULAR_GEN %.1f" % this_val)
                elif not is_system_star_claimed(system):
                    # still has extra value as an alternate location for generators & for blocking enemies generators
                    star_bonus += this_val * backup_factor
                    detail.append("PRO_SINGULAR_GEN Backup %.1f" %
                                  (this_val * backup_factor))
            elif system.starType == fo.starType.red and not has_claimed_star(
                    fo.starType.blackHole):
                rfactor = (1.0 + count_claimed_stars(fo.starType.red))**-2
                star_bonus += 40 * discount_multiplier * backup_factor * rfactor  # can be used for artif'l black hole
                detail.append(
                    "Red Star for Art Black Hole %.1f" %
                    (40 * discount_multiplier * backup_factor * rfactor))
        if tech_is_complete(
                "PRO_NEUTRONIUM_EXTRACTION"
        ) or "PRO_NEUTRONIUM_EXTRACTION" in empire_research_list[:8]:
            if system.starType in [fo.starType.neutron]:
                if not has_claimed_star(fo.starType.neutron):
                    star_bonus += 80 * discount_multiplier  # pretty rare planets, good for armor
                    detail.append("PRO_NEUTRONIUM_EXTRACTION %.1f" %
                                  (80 * discount_multiplier))
                else:
                    # still has extra value as an alternate location for generators & for bnlocking enemies generators
                    star_bonus += 20 * discount_multiplier * backup_factor
                    detail.append("PRO_NEUTRONIUM_EXTRACTION Backup %.1f" %
                                  (20 * discount_multiplier * backup_factor))
        if tech_is_complete(
                "SHP_ENRG_BOUND_MAN"
        ) or "SHP_ENRG_BOUND_MAN" in empire_research_list[:6]:
            # TODO: base this on pilot val, and also consider red stars
            if system.starType in [fo.starType.blackHole, fo.starType.blue]:
                init_val = 100 * discount_multiplier * (pilot_val or 1)
                if not has_claimed_star(fo.starType.blackHole,
                                        fo.starType.blue):
                    colony_star_bonus += init_val  # pretty rare planets, good for energy shipyards
                    detail.append("SHP_ENRG_BOUND_MAN %.1f" % init_val)
                elif not is_system_star_claimed(system):
                    # still has extra value as an alternate location for energy shipyard
                    colony_star_bonus += 0.5 * init_val * backup_factor
                    detail.append("SHP_ENRG_BOUND_MAN Backup %.1f" %
                                  (0.5 * init_val * backup_factor))
    retval += star_bonus

    planet_specials = list(planet.specials)
    if "ECCENTRIC_ORBIT_SPECIAL" in planet.specials:
        fixed_res += discount_multiplier * 6
        detail.append("ECCENTRIC_ORBIT_SPECIAL %.1f" %
                      (discount_multiplier * 6))

    if mission_type == MissionType.OUTPOST or (
            mission_type == MissionType.INVASION and not species_name):

        if "ANCIENT_RUINS_SPECIAL" in planet.specials:  # TODO: add value for depleted ancient ruins
            retval += discount_multiplier * 30
            detail.append("Undepleted Ruins %.1f" % discount_multiplier * 30)

        for special in planet_specials:
            if "_NEST_" in special:
                nest_val = get_nest_rating(
                    special, 5.0
                ) * discount_multiplier  # get an outpost on the nest quick
                retval += nest_val
                detail.append("%s %.1f" % (special, nest_val))
            elif special == "FORTRESS_SPECIAL":
                fort_val = 10 * discount_multiplier
                retval += fort_val
                detail.append("%s %.1f" % (special, fort_val))
            elif special == "HONEYCOMB_SPECIAL":
                honey_val = 0.3 * (AIDependencies.HONEYCOMB_IND_MULTIPLIER *
                                   AIDependencies.INDUSTRY_PER_POP *
                                   population_with_industry_focus() *
                                   discount_multiplier)
                retval += honey_val
                detail.append("%s %.1f" % (special, honey_val))
        if planet.size == fo.planetSize.asteroids:
            ast_val = 0
            if system:
                for pid in system.planetIDs:
                    other_planet = universe.getPlanet(pid)
                    if other_planet.size == fo.planetSize.asteroids:
                        if pid == planet_id:
                            continue
                        elif pid < planet_id and planet.unowned:
                            ast_val = 0
                            break
                    elif other_planet.speciesName:
                        if other_planet.owner == empire.empireID:
                            ownership_factor = 1.0
                        elif pid in prospective_invasion_targets:
                            ownership_factor = character.secondary_valuation_factor_for_invasion_targets(
                            )
                        else:
                            ownership_factor = 0.0
                        ast_val += ownership_factor * _base_asteroid_mining_val(
                        ) * discount_multiplier
                retval += ast_val
                if ast_val > 0:
                    detail.append("AsteroidMining %.1f" % ast_val)
            ast_val = 0
            if tech_is_complete("SHP_ASTEROID_HULLS"):
                per_ast = 20
            elif tech_is_complete("CON_ORBITAL_CON"):
                per_ast = 5
            else:
                per_ast = 0.1
            if system:
                for pid in system.planetIDs:
                    other_planet = universe.getPlanet(pid)
                    if other_planet.size == fo.planetSize.asteroids:
                        if pid == planet_id:
                            continue
                        elif pid < planet_id and planet.unowned:
                            ast_val = 0
                            break
                    elif other_planet.speciesName:
                        other_species = fo.getSpecies(other_planet.speciesName)
                        if other_species and other_species.canProduceShips:
                            if other_planet.owner == empire.empireID:
                                ownership_factor = 1.0
                            elif pid in prospective_invasion_targets:
                                ownership_factor = character.secondary_valuation_factor_for_invasion_targets(
                                )
                            else:
                                ownership_factor = 0.0
                            ast_val += ownership_factor * per_ast * discount_multiplier
                retval += ast_val
                if ast_val > 0:
                    detail.append("AsteroidShipBuilding %.1f" % ast_val)
        # We will assume that if any GG in the system is populated, they all will wind up populated; cannot then hope
        # to build a GGG on a non-populated GG
        populated_gg_factor = 1.0
        per_gg = 0
        if planet.size == fo.planetSize.gasGiant:
            # TODO: Given current industry calc approach, consider bringing this max val down to actual max val of 10
            if tech_is_complete("PRO_ORBITAL_GEN"):
                per_gg = 20
            elif tech_is_complete("CON_ORBITAL_CON"):
                per_gg = 10
            if species_name:
                populated_gg_factor = 0.5
        else:
            per_gg = 5
        if system:
            gg_list = []
            orb_gen_val = 0
            gg_detail = []
            for pid in system.planetIDs:
                other_planet = universe.getPlanet(pid)
                if other_planet.size == fo.planetSize.gasGiant:
                    gg_list.append(pid)
                    if other_planet.speciesName:
                        populated_gg_factor = 0.5
                if (pid != planet_id and other_planet.owner == empire.empireID
                        and FocusType.FOCUS_INDUSTRY
                        in list(other_planet.availableFoci) +
                    [other_planet.focus]):
                    orb_gen_val += per_gg * discount_multiplier
                    # Note, this reported value may not take into account a later adjustment from a populated gg
                    gg_detail.append("GGG for %s %.1f" %
                                     (other_planet.name, discount_multiplier *
                                      per_gg * populated_gg_factor))
            if planet_id in sorted(gg_list)[:1]:
                retval += orb_gen_val * populated_gg_factor
                detail.extend(gg_detail)
            else:
                detail.append("Won't GGG")
        if existing_presence:
            detail.append("preexisting system colony")
            retval = (retval + existing_presence *
                      _get_defense_value(species_name)) * 1.5

        # Fixme - sys_supply is always <= 0 leading to incorrect supply bonus score
        supply_val = 0
        if sys_supply < 0:
            if sys_supply + planet_supply >= 0:
                supply_val += 30 * (planet_supply - max(-3, sys_supply))
            else:
                retval += 30 * (planet_supply + sys_supply)  # a penalty
        elif planet_supply > sys_supply and (
                sys_supply < 2):  # TODO: check min neighbor supply
            supply_val += 25 * (planet_supply - sys_supply)
        detail.append("sys_supply: %d, planet_supply: %d, supply_val: %.0f" %
                      (sys_supply, planet_supply, supply_val))
        retval += supply_val

        if threat_factor < 1.0:
            threat_factor = _revise_threat_factor(threat_factor, retval,
                                                  this_sysid,
                                                  MINIMUM_COLONY_SCORE)
            retval *= threat_factor
            detail.append("threat reducing value by %3d %%" %
                          (100 * (1 - threat_factor)))
        return int(retval)
    else:  # colonization mission
        if not species:
            return 0
        supply_val = 0
        if "ANCIENT_RUINS_SPECIAL" in planet.specials:
            retval += discount_multiplier * 50
            detail.append("Undepleted Ruins %.1f" % discount_multiplier * 50)
        if "HONEYCOMB_SPECIAL" in planet.specials:
            honey_val = (AIDependencies.HONEYCOMB_IND_MULTIPLIER *
                         AIDependencies.INDUSTRY_PER_POP *
                         population_with_industry_focus() *
                         discount_multiplier)
            if FocusType.FOCUS_INDUSTRY not in species_foci:
                honey_val *= -0.3  # discourage settlement by colonizers not able to use Industry Focus
            retval += honey_val
            detail.append("%s %.1f" % ("HONEYCOMB_SPECIAL", honey_val))

        # Fixme - sys_supply is always <= 0 leading to incorrect supply bonus score
        if sys_supply <= 0:
            if sys_supply + planet_supply >= 0:
                supply_val = 40 * (planet_supply - max(-3, sys_supply))
            else:
                supply_val = 200 * (planet_supply + sys_supply)  # a penalty
                if species_name == "SP_SLY":
                    # Sly are essentially stuck with lousy supply, so don't penalize for that
                    supply_val = 0
        elif planet_supply > sys_supply == 1:  # TODO: check min neighbor supply
            supply_val = 20 * (planet_supply - sys_supply)
        detail.append("sys_supply: %d, planet_supply: %d, supply_val: %.0f" %
                      (sys_supply, planet_supply, supply_val))

        # if AITags != "":
        # print "Species %s has AITags %s"%(specName, AITags)

        retval += fixed_res
        retval += colony_star_bonus
        asteroid_bonus = 0
        gas_giant_bonus = 0
        flat_industry = 0
        mining_bonus = 0
        per_ggg = 10

        asteroid_factor = 0.0
        gg_factor = 0.0
        ast_shipyard_name = ""
        if system and FocusType.FOCUS_INDUSTRY in species.foci:
            for pid in system.planetIDs:
                if pid == planet_id:
                    continue
                p2 = universe.getPlanet(pid)
                if p2:
                    if p2.size == fo.planetSize.asteroids:
                        this_factor = 0.0
                        if p2.owner == empire.empireID:
                            this_factor = 1.0
                        elif p2.unowned:
                            this_factor = 0.5
                        elif pid in prospective_invasion_targets:
                            this_factor = character.secondary_valuation_factor_for_invasion_targets(
                            )
                        if this_factor > asteroid_factor:
                            asteroid_factor = this_factor
                            ast_shipyard_name = p2.name
                    if p2.size == fo.planetSize.gasGiant:
                        if p2.owner == empire.empireID:
                            gg_factor = max(gg_factor, 1.0)
                        elif p2.unowned:
                            gg_factor = max(gg_factor, 0.5)
                        elif pid in prospective_invasion_targets:
                            gg_factor = max(
                                gg_factor,
                                character.
                                secondary_valuation_factor_for_invasion_targets(
                                ))
        if asteroid_factor > 0.0:
            if tech_is_complete(
                    "PRO_MICROGRAV_MAN"
            ) or "PRO_MICROGRAV_MAN" in empire_research_list[:10]:
                flat_industry += 2 * asteroid_factor  # will go into detailed industry projection
                detail.append("Asteroid mining ~ %.1f" %
                              (5 * asteroid_factor * discount_multiplier))
            if tech_is_complete(
                    "SHP_ASTEROID_HULLS"
            ) or "SHP_ASTEROID_HULLS" in empire_research_list[:11]:
                if species and species.canProduceShips:
                    asteroid_bonus = 30 * discount_multiplier * pilot_val
                    detail.append("Asteroid ShipBuilding from %s %.1f" %
                                  (ast_shipyard_name,
                                   discount_multiplier * 30 * pilot_val))
        if gg_factor > 0.0:
            if tech_is_complete(
                    "PRO_ORBITAL_GEN"
            ) or "PRO_ORBITAL_GEN" in empire_research_list[:5]:
                flat_industry += per_ggg * gg_factor  # will go into detailed industry projection
                detail.append("GGG ~ %.1f" %
                              (per_ggg * gg_factor * discount_multiplier))

        # calculate the maximum population of the species on that planet.
        if planet.speciesName not in AIDependencies.SPECIES_FIXED_POPULATION:
            max_pop_size = calc_max_pop(planet, species, detail)
        else:
            max_pop_size = AIDependencies.SPECIES_FIXED_POPULATION[
                planet.speciesName]
            detail.append("Fixed max population of %.2f" % max_pop_size)

        if max_pop_size <= 0:
            detail.append(
                "Non-positive population projection for species '%s', so no colonization value"
                % (species and species.name))
            return 0

        for special in [
                "MINERALS_SPECIAL", "CRYSTALS_SPECIAL", "ELERIUM_SPECIAL"
        ]:
            if special in planet_specials:
                mining_bonus += 1

        has_blackhole = has_claimed_star(fo.starType.blackHole)
        ind_tech_map_flat = AIDependencies.INDUSTRY_EFFECTS_FLAT_NOT_MODIFIED_BY_SPECIES
        ind_tech_map_before_species_mod = AIDependencies.INDUSTRY_EFFECTS_PER_POP_MODIFIED_BY_SPECIES
        ind_tech_map_after_species_mod = AIDependencies.INDUSTRY_EFFECTS_PER_POP_NOT_MODIFIED_BY_SPECIES

        ind_mult = 1
        for tech in ind_tech_map_before_species_mod:
            if tech_is_complete(tech) and (
                    tech != AIDependencies.PRO_SINGULAR_GEN or has_blackhole):
                ind_mult += ind_tech_map_before_species_mod[tech]

        ind_mult = ind_mult * max(
            ind_tag_mod, 0.5 *
            (ind_tag_mod +
             res_tag_mod))  # TODO: report an actual calc for research value

        for tech in ind_tech_map_after_species_mod:
            if tech_is_complete(tech) and (
                    tech != AIDependencies.PRO_SINGULAR_GEN or has_blackhole):
                ind_mult += ind_tech_map_after_species_mod[tech]

        max_ind_factor = 0
        for tech in ind_tech_map_flat:
            if tech_is_complete(tech):
                fixed_ind += discount_multiplier * ind_tech_map_flat[tech]

        if FocusType.FOCUS_INDUSTRY in species.foci:
            if "TIDAL_LOCK_SPECIAL" in planet.specials:
                ind_mult += 1
            max_ind_factor += AIDependencies.INDUSTRY_PER_POP * mining_bonus
            max_ind_factor += AIDependencies.INDUSTRY_PER_POP * ind_mult
        cur_pop = 1.0  # assume an initial colonization value
        if planet.speciesName != "":
            cur_pop = planet.currentMeterValue(fo.meterType.population)
        elif tech_is_complete("GRO_LIFECYCLE_MAN"):
            cur_pop = 3.0
        cur_industry = planet.currentMeterValue(fo.meterType.industry)
        ind_val = _project_ind_val(cur_pop, max_pop_size, cur_industry,
                                   max_ind_factor, flat_industry,
                                   discount_multiplier)
        detail.append("ind_val %.1f" % ind_val)
        # used to give preference to closest worlds

        for special in [
                spec for spec in planet_specials
                if spec in AIDependencies.metabolismBoosts
        ]:
            # TODO: also consider potential future benefit re currently unpopulated planets
            gbonus = (discount_multiplier * AIDependencies.INDUSTRY_PER_POP *
                      ind_mult * empire_metabolisms.get(
                          AIDependencies.metabolismBoosts[special], 0)
                      )  # due to growth applicability to other planets
            growth_val += gbonus
            detail.append("Bonus for %s: %.1f" % (special, gbonus))

        if FocusType.FOCUS_RESEARCH in species.foci:
            research_bonus += discount_multiplier * 2 * AIDependencies.RESEARCH_PER_POP * max_pop_size
            if "ANCIENT_RUINS_SPECIAL" in planet.specials or "ANCIENT_RUINS_DEPLETED_SPECIAL" in planet.specials:
                research_bonus += discount_multiplier * 2 * AIDependencies.RESEARCH_PER_POP * max_pop_size * 5
                detail.append("Ruins Research")
            if "TEMPORAL_ANOMALY_SPECIAL" in planet.specials:
                research_bonus += discount_multiplier * 2 * AIDependencies.RESEARCH_PER_POP * max_pop_size * 25
                detail.append("Temporal Anomaly Research")
            if AIDependencies.COMPUTRONIUM_SPECIAL in planet.specials:
                comp_bonus = (0.5 * AIDependencies.TECH_COST_MULTIPLIER *
                              AIDependencies.RESEARCH_PER_POP *
                              AIDependencies.COMPUTRONIUM_RES_MULTIPLIER *
                              population_with_research_focus() *
                              discount_multiplier)
                if have_computronium():
                    comp_bonus *= backup_factor
                research_bonus += comp_bonus
                detail.append(AIDependencies.COMPUTRONIUM_SPECIAL)

        retval += (max(ind_val + asteroid_bonus + gas_giant_bonus,
                       research_bonus, growth_val) + fixed_ind + fixed_res +
                   supply_val)
        if existing_presence:
            detail.append("preexisting system colony")
            retval = (retval +
                      existing_presence * _get_defense_value(species_name)) * 2
        if threat_factor < 1.0:
            threat_factor = _revise_threat_factor(threat_factor, retval,
                                                  this_sysid,
                                                  MINIMUM_COLONY_SCORE)
            retval *= threat_factor
            detail.append("threat reducing value by %3d %%" %
                          (100 * (1 - threat_factor)))
    return retval
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]

    color = empire.colour

    part_meters = ship.partMeters

    meter = planet.getMeter(fo.meterType.population)

    inspect(
        fo,
        instances=[
            meter,
            part_meters,
            color,
            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.acceptPeaceProposal),
            fleets_int_vector,
            part_type,
            prod_queue,
            prod_queue.allocatedPP,
            prod_queue[0],
            research_queue,
            research_queue[0],
            empire.getSitRep(0),
            universe.getBuilding(building)
        ],
        classes_to_ignore=(
            'IntSet', 'StringSet', 'IntIntMap', 'ShipSlotVec', 'VisibilityIntMap', 'IntDblMap',
            'IntBoolMap', 'ItemSpecVec', 'PairIntInt_IntMap', 'IntSetSet', 'StringVec',
            'IntPairVec', 'IntFltMap', 'MeterTypeStringPair', 'MeterTypeMeterMap', 'universeObject',
            # this item cannot be get from generate orders
            'diplomaticStatusUpdate',
        ),
        path='AI'
    )
    exit(1)  # exit game to main menu no need to play anymore.
示例#50
0
def getColonyFleets():
    "get colony fleets"

    allColonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)
    AIstate.colonyFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allColonyFleetIDs)

    # get suppliable systems and planets
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    capitalID = empire.capitalID
    homeworld = universe.getPlanet(capitalID)
    speciesName = homeworld.speciesName
    species = fo.getSpecies(speciesName)

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

    # get outpost and colonization planets
    exploredSystemIDs = empire.exploredSystemIDs
    print "Explored SystemIDs: " + str(list(exploredSystemIDs))

    exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs)
    print "Explored PlanetIDs: " + str(exploredPlanetIDs)
    print ""

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

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

    unpopulatedPlanetIDs = list(set(exploredPlanetIDs) - set(allOwnedPlanetIDs))
    print "Unpopulated PlanetIDs:             " + str(unpopulatedPlanetIDs)

    print ""
    colonyTargetedPlanetIDs = getColonyTargetedPlanetIDs(
        universe.planetIDs, AIFleetMissionType.FLEET_MISSION_COLONISATION, empireID
    )
    print "Colony Targeted PlanetIDs:         " + str(colonyTargetedPlanetIDs)

    colonyFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)
    if not colonyFleetIDs:
        print "Available Colony Fleets:             0"
    else:
        print "Colony FleetIDs:                   " + str(
            FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_COLONISATION)
        )

    numColonyFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(colonyFleetIDs))
    print "Colony Fleets Without Missions:      " + str(numColonyFleets)

    print ""
    outpostTargetedPlanetIDs = getOutpostTargetedPlanetIDs(
        universe.planetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, empireID
    )
    print "Outpost Targeted PlanetIDs:        " + str(outpostTargetedPlanetIDs)

    outpostFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST)
    if not outpostFleetIDs:
        print "Available Outpost Fleets:            0"
    else:
        print "Outpost FleetIDs:                  " + str(
            FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_OUTPOST)
        )

    numOutpostFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(outpostFleetIDs))
    print "Outpost Fleets Without Missions:     " + str(numOutpostFleets)

    evaluatedColonyPlanetIDs = list(set(unpopulatedPlanetIDs) - set(colonyTargetedPlanetIDs))
    # print "Evaluated Colony PlanetIDs:        " + str(evaluatedColonyPlanetIDs)

    evaluatedOutpostPlanetIDs = list(set(unpopulatedPlanetIDs) - set(outpostTargetedPlanetIDs))
    # print "Evaluated Outpost PlanetIDs:       " + str(evaluatedOutpostPlanetIDs)

    evaluatedColonyPlanets = assignColonisationValues(
        evaluatedColonyPlanetIDs,
        AIFleetMissionType.FLEET_MISSION_COLONISATION,
        fleetSupplyablePlanetIDs,
        species,
        empire,
    )
    removeLowValuePlanets(evaluatedColonyPlanets)

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

    print ""
    print "Settleable Colony PlanetIDs:"
    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)

    evaluatedOutpostPlanets = assignColonisationValues(
        evaluatedOutpostPlanetIDs, AIFleetMissionType.FLEET_MISSION_OUTPOST, fleetSupplyablePlanetIDs, species, empire
    )
    removeLowValuePlanets(evaluatedOutpostPlanets)

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

    print "Settleable Outpost PlanetIDs:"
    for evaluationPair in sortedOutposts:
        print "    ID|Score: " + str(evaluationPair)
    print ""

    # export outposts for other AI modules
    AIstate.colonisableOutpostIDs = sortedOutposts