Example #1
0
def resumeLoadedGame(saved_state_string):  # pylint: disable=invalid-name
    """Called by client to when resume a loaded game."""
    if fo.getEmpire() is None:
        print "This client has no empire. Doing nothing to resume loaded game."
        return    
    
    if fo.getEmpire().eliminated:
        print "This empire has been eliminated. Ignoring resume loaded game."
        return
    turn_timer.start("Server Processing")

    global foAIstate
    print "Resuming loaded game"
    if not saved_state_string:
        print_error("AI given empty state-string to resume from; this is expected if the AI is assigned to an empire "
                    "previously run by a human, but is otherwise an error. AI will be set to Aggressive.")
        foAIstate = AIstate.AIstate(fo.aggression.aggressive)
        foAIstate.session_start_cleanup()
    else:
        try:
            # loading saved state
            # pre load code
            foAIstate = pickle.loads(saved_state_string)
        except Exception as e:
            # assigning new state
            foAIstate = AIstate.AIstate(fo.aggression.aggressive)
            foAIstate.session_start_cleanup()
            print_error("Fail to load aiState from saved game: %s" % e)

    aggression_trait = foAIstate.character.get_trait(Aggression)
    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression_trait.key, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Example #2
0
 def handle_diplomatic_message(self, message):
     """Handle a diplomatic message update from the server,
     such as if another player declares war, accepts peace, or cancels a proposed peace treaty.
     :param message: message.recipient and message.sender are respective empire IDs
     :return:
     """
     debug("Received diplomatic %s message from %s to %s." % (
         message.type, fo.getEmpire(message.sender),
         'me' if message.recipient == fo.empireID() else fo.getEmpire(message.recipient)))
     # TODO: remove the following early return once proper support for third party diplomatic history is added
     if message.recipient != fo.empireID():
         return
     aistate = get_aistate()
     if message.type == fo.diplomaticMessageType.peaceProposal:
         aistate.log_peace_request(message.sender, message.recipient)
         proposal_sender_player = fo.empirePlayerID(message.sender)
         attitude = aistate.character.attitude_to_empire(message.sender, aistate.diplomatic_logs)
         possible_acknowledgments = []
         aggression = aistate.character.get_trait(Aggression)
         if aggression.key <= fo.aggression.typical:
             possible_acknowledgments = UserStringList("AI_PEACE_PROPOSAL_ACKNOWLEDGEMENTS_MILD_LIST")
             if attitude > 0:
                 possible_replies = UserStringList("AI_PEACE_PROPOSAL_RESPONSES_YES_MILD_LIST")
             else:
                 possible_replies = UserStringList("AI_PEACE_PROPOSAL_RESPONSES_NO_MILD_LIST")
         else:
             possible_acknowledgments = UserStringList("AI_PEACE_PROPOSAL_ACKNOWLEDGEMENTS_HARSH_LIST")
             if attitude > 0:
                 possible_replies = UserStringList("AI_PEACE_PROPOSAL_RESPONSES_YES_HARSH_LIST")
             else:
                 possible_replies = UserStringList("AI_PEACE_PROPOSAL_RESPONSES_NO_HARSH_LIST")
         acknowledgement = random.choice(possible_acknowledgments)
         reply_text = random.choice(possible_replies)
         debug("Acknowledging proposal with initial message (from %d choices): '%s'" % (
             len(possible_acknowledgments), acknowledgement))
         fo.sendChatMessage(proposal_sender_player, acknowledgement)
         if attitude > 0:
             diplo_reply = fo.diplomaticMessage(message.recipient, message.sender,
                                                fo.diplomaticMessageType.acceptPeaceProposal)
             debug("Sending diplomatic message to empire %s of type %s" % (message.sender, diplo_reply.type))
             fo.sendDiplomaticMessage(diplo_reply)
         debug("sending chat to player %d of empire %d, message body: '%s'" % (
             proposal_sender_player, message.sender, reply_text))
         fo.sendChatMessage(proposal_sender_player, reply_text)
     elif message.type == fo.diplomaticMessageType.warDeclaration:
         # note: apparently this is currently (normally?) sent not as a warDeclaration,
         # but as a simple diplomatic_status_update to war
         aistate.log_war_declaration(message.sender, message.recipient)
Example #3
0
def _planned_species() -> Mapping[PlanetId, SpeciesName]:
    universe = fo.getUniverse()
    production_queue = fo.getEmpire().productionQueue
    planned_species = {}
    colonisation_plans = get_aistate().colonisablePlanetIDs
    for element in production_queue:
        species_name = _get_species_from_colony_building(element.name)
        if species_name:
            planned_species[element.locationID] = species_name
    for pid in get_owned_planets_by_empire():
        planet = universe.getPlanet(pid)
        if planet.speciesName:
            # skip already populated planets
            continue
        # Finished colony buildings are normal buildings for one turn before turning the outpost into a colony
        for building in map(universe.getBuilding, planet.buildingIDs):
            species_name = _get_species_from_colony_building(building.name)
            if species_name:
                planned_species[pid] = species_name
                break
        if pid not in planned_species:
            # Without checking the colonisation plans, the AI may start building a colony and buildings
            # the future species wouldn't like in the same turn.
            plan = colonisation_plans.get(pid)
            if plan:
                planned_species[pid] = plan[1]
    debug(f"Planned species: {planned_species}")
    return planned_species
Example #4
0
def calculateExplorationPriority():
    """calculates the demand for scouts by unexplored systems"""
    global scoutsNeeded

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    numUnexploredSystems = len( ExplorationAI.borderUnexploredSystemIDs )  #len(foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED))
    numScouts = sum( [ foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) for fid in FleetUtilsAI.get_empire_fleet_ids_by_role(
        EnumsAI.AIFleetMissionType.FLEET_MISSION_EXPLORATION)] ) # FleetUtilsAI.get_empire_fleet_ids_by_role(AIFleetMissionType.FLEET_MISSION_EXPLORATION)
    productionQueue = empire.productionQueue
    queuedScoutShips=0
    for queue_index in range(0, len(productionQueue)):
        element=productionQueue[queue_index]
        if element.buildType == EnumsAI.AIEmpireProductionTypes.BT_SHIP:
            if foAI.foAIstate.get_ship_role(element.designID) == EnumsAI.AIShipRoleType.SHIP_ROLE_CIVILIAN_EXPLORATION :
                queuedScoutShips += element.remaining * element.blocksize

    milShips = MilitaryAI.num_milships
    # intent of the following calc is essentially 
    # new_scouts_needed = min(need_cap_A, need_cap_B, base_need) - already_got_or_queued
    # where need_cap_A is to help prevent scouting needs from swamping military needs, and 
    # need_cap_B is to help regulate investment into scouting while the empire is small.
    # These caps could perhaps instead be tied more directly to military priority and 
    # total empire production.
    scoutsNeeded = max(0, min( 4+int(milShips/5), 4+int(fo.currentTurn()/50) , 2+ numUnexploredSystems**0.5 ) - numScouts - queuedScoutShips )
    explorationPriority = int(40*scoutsNeeded)

    print
    print "Number of Scouts : " + str(numScouts)
    print "Number of Unexplored systems: " + str(numUnexploredSystems)
    print "military size: ", milShips
    print "Priority for scouts : " + str(explorationPriority)

    return explorationPriority
Example #5
0
def startNewGame(aggression=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring new game start message."
        return

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

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

    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Example #6
0
def can_travel_to_system_and_return_to_resupply(fleet_id, from_system_target, to_system_target):
    """
    Filter systems where fleet can travel from starting system. # TODO rename function

    :param fleet_id:
    :type fleet_id: int
    :param from_system_target:
    :type from_system_target: universe_object.System
    :param to_system_target:
    :type to_system_target: universe_object.System
    :return:
    :rtype: list
    """
    system_targets = []
    if not from_system_target.id == to_system_target.id:
        fleet_supplyable_system_ids = fo.getEmpire().fleetSupplyableSystemIDs
        fuel = int(FleetUtilsAI.get_fuel(fleet_id))  # int to get actual number of jumps
        max_fuel = int(FleetUtilsAI.get_max_fuel(fleet_id))
        # try to find path without going resupply first
        supply_system_target = get_nearest_supplied_system(to_system_target.id)
        system_targets = __find_path_with_fuel_to_system_with_possible_return(from_system_target, to_system_target, system_targets, fleet_supplyable_system_ids, max_fuel, fuel, supply_system_target)
        # resupply in system first is required to find path
        if from_system_target.id not in fleet_supplyable_system_ids and not system_targets:
            # add supply system to visit
            from_system_target = get_nearest_supplied_system(from_system_target.id)
            system_targets.append(from_system_target)
            # find path from supplied system to wanted system
            system_targets = __find_path_with_fuel_to_system_with_possible_return(from_system_target, to_system_target, system_targets, fleet_supplyable_system_ids, max_fuel, max_fuel, supply_system_target)
    return system_targets
Example #7
0
def prepareForSave():  # pylint: disable=invalid-name
    """Called by client when the game is about to be saved, to let the Python AI know it should save any AI state
    information, such as plans or knowledge about the game from previous turns,
    in the state string so that they can be restored if the game is loaded."""
    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Doing nothing to prepare for save.")
        return

    if empire.eliminated:
        info("This empire has been eliminated. Save info request")
        return

    info("Preparing for game save by serializing state")

    # serialize (convert to string) global state dictionary and send to AI client to be stored in save file
    import savegame_codec

    try:
        dump_string = savegame_codec.build_savegame_string()
        fo.setSaveStateString(dump_string)
    except Exception as e:
        error(
            "Failed to encode the AIstate as save-state string. "
            "The resulting save file should be playable but the AI "
            "may have a different aggression. The error raised was: %s" % e,
            exc_info=True,
        )
Example #8
0
def can_travel_to_system_and_return_to_resupply(fleet_id, from_system_target, to_system_target):
    """ Check if fleet can travel from starting system to wanted system."""
    system_targets = []
    if not from_system_target.target_id == to_system_target.target_id:
        # get supplyable systems
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        # get current fuel and max fuel
        universe = fo.getUniverse()
        fleet = universe.getFleet(fleet_id)
        max_fuel = int(fleet.maxFuel)
        fuel = int(fleet.fuel)
        #if verbose:
        # print "   fleet ID %d has %.1f fuel to get from %s to %s"%(fleetID, fuel, fromSystemAITarget, toSystemAITarget )

        # try to find path without going resupply first
        supply_system_target = get_nearest_supplied_system(to_system_target.target_id)
        system_targets = __find_path_with_fuel_to_system_with_possible_return(from_system_target, to_system_target, system_targets, fleet_supplyable_system_ids, max_fuel, fuel, supply_system_target)
        # resupply in system first is required to find path
        if not from_system_target.target_id in fleet_supplyable_system_ids and not system_targets:
            # add supply system to visit
            from_system_target = get_nearest_supplied_system(from_system_target.target_id)
            system_targets.append(from_system_target)
            # find path from supplied system to wanted system
            system_targets = __find_path_with_fuel_to_system_with_possible_return(from_system_target, to_system_target, system_targets, fleet_supplyable_system_ids, max_fuel, max_fuel, supply_system_target)
    return system_targets
Example #9
0
def trooper_move_reqs_met(main_fleet_mission, order, verbose):
    """
    Indicates whether or not move requirements specific to invasion troopers are met for the provided mission and order.
    :type main_fleet_mission: AIFleetMission.AIFleetMission
    :type order: OrderMove
    :param verbose: whether to print verbose decision details
    :type verbose: bool
    :rtype: bool
    """
    # Don't advance outside of our fleet-supply zone unless the target either has no shields at all or there
    # is already a military fleet assigned to secure the target, and don't take final jump unless the planet is
    # (to the AI's knowledge) down to zero shields.  Additional checks will also be done by the later
    # generic movement code
    invasion_target = main_fleet_mission.target
    invasion_planet = invasion_target.get_object()
    invasion_system = invasion_target.get_system()
    supplied_systems = fo.getEmpire().fleetSupplyableSystemIDs
    # if about to leave supply lines
    if order.target.id not in supplied_systems or fo.getUniverse(
    ).jumpDistance(order.fleet.id, invasion_system.id) < 5:
        if invasion_planet.currentMeterValue(fo.meterType.maxShield):
            military_support_fleets = MilitaryAI.get_military_fleets_with_target_system(
                invasion_system.id)
            if not military_support_fleets:
                if verbose:
                    debug(
                        "trooper_move_reqs_met() holding Invasion fleet %d before leaving supply "
                        "because target (%s) has nonzero max shields and there is not yet a military fleet "
                        "assigned to secure the target system." %
                        (order.fleet.id, invasion_planet))
                return False

            # if there is a threat in the enemy system, do give military ships at least 1 turn to clear it
            delay_to_move_troops = 1 if MilitaryAI.get_system_local_threat(
                order.target.id) else 0

            def eta(fleet_id):
                return FleetUtilsAI.calculate_estimated_time_of_arrival(
                    fleet_id, invasion_system.id)

            eta_this_fleet = eta(order.fleet.id)
            if all(((eta_this_fleet -
                     delay_to_move_troops) <= eta(fid) and eta(fid))
                   for fid in military_support_fleets):
                if verbose:
                    debug(
                        "trooper_move_reqs_met() holding Invasion fleet %d before leaving supply "
                        "because target (%s) has nonzero max shields and no assigned military fleet would arrive"
                        "at least %d turn earlier than the invasion fleet" %
                        (order.fleet.id, invasion_planet,
                         delay_to_move_troops))
                return False

        if verbose:
            debug(
                "trooper_move_reqs_met() allowing Invasion fleet %d to leave supply "
                "because target (%s) has zero max shields or there is a military fleet assigned to secure "
                "the target system which will arrive at least 1 turn before the invasion fleet.",
                order.fleet.id, invasion_planet)
    return True
Example #10
0
def getInvasionFleets():
    "get invasion fleets"

    allInvasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION)
    AIstate.invasionFleetIDs = FleetUtilsAI.extractFleetIDsWithoutMissionTypes(allInvasionFleetIDs)

    # get supplyable planets
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID

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

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

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

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

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

    print ""
    print "Invasion Targeted SystemIDs:       " + str(AIstate.invasionTargetedSystemIDs)
    invasionTargetedPlanetIDs = getInvasionTargetedPlanetIDs(universe.planetIDs, AIFleetMissionType.FLEET_MISSION_INVASION, empireID)
    allInvasionTargetedSystemIDs = PlanetUtilsAI.getSystems(invasionTargetedPlanetIDs)
 
    # export invasion targeted systems for other AI modules
    AIstate.invasionTargetedSystemIDs = allInvasionTargetedSystemIDs
    print "Invasion Targeted PlanetIDs:       " + str(invasionTargetedPlanetIDs)

    invasionFleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION)
    if not invasionFleetIDs:
        print "Available Invasion Fleets:           0"
    else:
        print "Invasion FleetIDs:                 " + str(FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_INVASION))
 
    numInvasionFleets = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(invasionFleetIDs))
    print "Invasion Fleets Without Missions:    " + str(numInvasionFleets)

    evaluatedPlanetIDs = list(set(competitorPlanetIDs) - set(invasionTargetedPlanetIDs))
    # print "Evaluated PlanetIDs:               " + str(evaluatedPlanetIDs)

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

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

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

    # export opponent planets for other AI modules
    AIstate.opponentPlanetIDs = sortedPlanets
Example #11
0
def printResourcesPriority():
    "calculate top resource priority"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    ownedPlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    print "Resource Management:"
    print ""
    print "Resource Priorities:"
    resourcePriorities = {}
    for priorityType in getAIPriorityResourceTypes():
        resourcePriorities[priorityType] = foAI.foAIstate.getPriority(priorityType)

    sortedPriorities = resourcePriorities.items()
    sortedPriorities.sort(lambda x,y: cmp(x[1], y[1]), reverse=True)
    topPriority = -1
    for evaluationPair in sortedPriorities:
        if topPriority < 0:
            topPriority = evaluationPair[0]
        print "    ID|Score: " + str(evaluationPair)

    print "  Top Resource Priority: " + str(topPriority)
    # what is the focus of available resource centers?
    print ""
    print "Planet Resources Foci:"
    for planetID in ownedPlanetIDs:
        planet = universe.getPlanet(planetID)
        planetPopulation = planet.currentMeterValue(fo.meterType.population)
        print "  ID: " + str(planetID) + " Name: " + str(planet.name) + " Type: " + str(planet.type) + " Size: " + str(planet.size) + " Focus: " + str(planet.focus) + " Species: " + str(planet.speciesName) + " Population: " + str(planetPopulation)
Example #12
0
def startNewGame(aggression=4):
    global __timerFile,  lastTurnTimestamp,  __timerBucketFile
    print "New game started, AI Agression level %d"%aggression

    # initialize AIstate
    global foAIstate
    foAIstate = AIstate.AIstate(aggression=aggression)
    foAIstate.sessionStartCleanup()
    print "Initialized foAIstate class"
    if __timerFile:
        __timerFile.close()
    if ResourcesAI.resourceTimerFile:
        ResourcesAI.resourceTimerFile.close()
    empireID = fo.getEmpire().empireID
    try:
        if os.path.exists("timers") and os.path.isdir("timers"):
            timerpath="timers"+os.path.sep+"timer_%02d.dat"%(empireID-1)
            __timerFile = open(timerpath,  'w')
            __timerFile.write("Turn\t" + "\t".join(__timerEntries) +'\n')
            timerBucketpath="timers"+os.path.sep+"timer_bucket_%02d.dat"%(empireID-1)
            __timerBucketFile = open(timerBucketpath,  'w')
            __timerBucketFile.write("Turn\t" + "\t".join(__timerBucketEntries) +'\n')
            lastTurnTimestamp = time() 
            if ResourcesAI.doResourceTiming:
                ResourcesAI.resourceTimerFile = open("timers"+os.path.sep+"resourceTimer_%2d.dat"%(empireID-1),  'w')
                ResourcesAI.resourceTimerFile.write("Turn\t"+ "\t".join(ResourcesAI.__timerEntries)+"\n")
            print "timer file saved at "+timerpath
    except:
        __timerFile=None
        ResourcesAI.resourceTimerFile  =None
        ResourcesAI.doResourceTiming = False
        print "Error: exception caught starting timing:  ",  traceback.format_exc()
        print "won't record timing info"
Example #13
0
def _calculate_exploration_priority():
    """Calculates the demand for scouts by unexplored systems."""
    empire = fo.getEmpire()
    num_unexplored_systems = len(ExplorationAI.border_unexplored_system_ids)
    num_scouts = sum([foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) for fid in FleetUtilsAI.get_empire_fleet_ids_by_role(
        MissionType.EXPLORATION)])
    production_queue = empire.productionQueue
    queued_scout_ships = 0
    for queue_index in range(0, len(production_queue)):
        element = production_queue[queue_index]
        if element.buildType == EmpireProductionTypes.BT_SHIP:
            if foAI.foAIstate.get_ship_role(element.designID) == ShipRoleType.CIVILIAN_EXPLORATION:
                queued_scout_ships += element.remaining * element.blocksize

    mil_ships = MilitaryAI.get_num_military_ships()
    # intent of the following calc is essentially
    # new_scouts_needed = min(need_cap_A, need_cap_B, base_need) - already_got_or_queued
    # where need_cap_A is to help prevent scouting needs from swamping military needs, and
    # need_cap_B is to help regulate investment into scouting while the empire is small.
    # These caps could perhaps instead be tied more directly to military priority and
    # total empire production.
    desired_number_of_scouts = int(min(4 + mil_ships/5, 4 + fo.currentTurn()/50.0, 2 + num_unexplored_systems**0.5))
    scouts_needed = max(0, desired_number_of_scouts - (num_scouts + queued_scout_ships))
    exploration_priority = int(40 * scouts_needed)

    print
    print "Number of Scouts: %s" % num_scouts
    print "Number of Unexplored systems: %s" % num_unexplored_systems
    print "Military size: %s" % mil_ships
    print "Priority for scouts: %s" % exploration_priority

    return exploration_priority
Example #14
0
def _get_modified_research_bonuses(planet: fo.planet) -> List[Bonus]:
    """
    Get list of per-population bonuses which are added before multiplication with the species skill value.
    """
    # use fo.getEmpire().researchQueue directly here to simplify caching this function
    specials = planet.specials
    return [
        Bonus(
            AIDependencies.ANCIENT_RUINS_SPECIAL in specials
            or AIDependencies.ANCIENT_RUINS_SPECIAL2 in specials,
            get_named_real("ANCIENT_RUINS_MIN_STABILITY"),
            get_named_real("ANCIENT_RUINS_TARGET_RESEARCH_PERPOP"),
        ),
        Bonus(
            fo.getEmpire().policyAdopted("PLC_DIVERSITY"),
            get_named_real("PLC_DIVERSITY_MIN_STABILITY"),
            (len(get_empire_planets_by_species()) -
             get_named_int("PLC_DIVERSITY_THRESHOLD")) *
            get_named_real("PLC_DIVERSITY_SCALING"),
        ),
        Bonus(
            tech_soon_available("GRO_ENERGY_META", 3),
            get_named_real("GRO_ENERGY_META_MIN_STABILITY"),
            get_named_real("GRO_ENERGY_META_TARGET_RESEARCH_PERPOP"),
        ),
        Bonus(
            bool(BuildingType.ENCLAVE_VOID.built_or_queued_at()),
            get_named_real("BLD_ENCLAVE_VOID_MIN_STABILITY"),
            get_named_real("BLD_ENCLAVE_VOID_TARGET_RESEARCH_PERPOP"),
        ),
    ]
Example #15
0
def dislike_factor() -> float:
    """Returns multiplier for dislike effects."""
    # See happiness.macros
    has_liberty = fo.getEmpire().policyAdopted("PLC_LIBERTY")
    # conformance not used yet
    return fo.getNamedValue(
        "PLC_LIBERTY_DISLIKE_FACTOR") if has_liberty else 1.0
Example #16
0
def startNewGame():  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Ignoring new game start message.")
        return

    if empire.eliminated:
        info(
            "This empire has been eliminated. Ignoring new game start message."
        )
        return
    # initialize AIstate
    debug("Initializing AI state...")
    aistate = create_new_aistate(_choose_aggression())
    aggression_trait = aistate.character.get_trait(Aggression)
    debug("New game started, AI Aggression level %d (%s)" %
          (aggression_trait.key, get_trait_name_aggression(aistate.character)))
    aistate.session_start_cleanup()
    debug("Initialization of AI state complete!")
    debug("Trying to rename our homeworld...")
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id != INVALID_ID:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([
            random.choice(possible_capitals(aistate.character)).strip(),
            planet.name
        ])
        debug("    Renaming to %s..." % new_name)
        res = fo.issueRenameOrder(planet_id, new_name)
        debug("    Result: %d; Planet is now named %s" % (res, planet.name))
    _pre_game_start(empire.empireID)
Example #17
0
 def print_resource_ai_footer():
     empire = fo.getEmpire()
     pp, rp = empire.productionPoints, empire.resourceProduction(fo.resourceType.research)
     # Next string used in charts. Don't modify it!
     print "Current Output (turn %4d) RP/PP : %.2f ( %.1f / %.1f )" % (fo.currentTurn(), rp / (pp + 0.0001), rp, pp)
     print "------------------------"
     print "ResourcesAI Time Requirements:"
Example #18
0
def calculateFoodPriority():
    "calculates the AI's need for food"
    # attempts to sustain a food stockpile whose size depends on the AI empires population
    # foodStockpile == 0 => returns 100, foodStockpile == foodTarget => returns 0

    empire = fo.getEmpire()
    foodProduction = empire.resourceProduction(fo.resourceType.food)
    foodStockpile = empire.resourceStockpile(fo.resourceType.food)
    foodTarget = 10 * empire.population() * AIstate.foodStockpileSize

    if (foodTarget == 0):
        return 0

    foodPriority = (foodTarget - foodStockpile) / foodTarget * 115

    print ""
    print "Food Production:        " + str(foodProduction)
    print "Size of Food Stockpile: " + str(foodStockpile)
    print "Target Food Stockpile : " + str (foodTarget)
    print "Priority for Food     : " + str(foodPriority)

    if foodPriority < 0:
        return 0

    return foodPriority
Example #19
0
def startNewGame(aggression=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring new game start message."
        return

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

    # initialize AIstate
    global foAIstate
    foAIstate = AIstate.AIstate(aggression=aggression)
    foAIstate.session_start_cleanup()
    print "Initialized foAIstate class"
    planet_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    if planet_id is not None and planet_id != -1:
        planet = universe.getPlanet(planet_id)
        new_name = " ".join([random.choice(_capitals.get(aggression, []) or [" "]).strip(), planet.name])
        print "Capitol City Names are: ", _capitals
        print "This Capitol New name is ", new_name
        res = fo.issueRenameOrder(planet_id, new_name)
        print "Capitol Rename attempt result: %d; planet now named %s" % (res, planet.name)

    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression, DiplomaticCorp.DiplomaticCorp)()
Example #20
0
def calculateExplorationPriority():
    """calculates the demand for scouts by unexplored systems"""
    global scoutsNeeded

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    numUnexploredSystems = len( ExplorationAI.borderUnexploredSystemIDs )  #len(foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED))
    numScouts = sum( [ foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) for fid in FleetUtilsAI.get_empire_fleet_ids_by_role(
        EnumsAI.AIFleetMissionType.FLEET_MISSION_EXPLORATION)] ) # FleetUtilsAI.get_empire_fleet_ids_by_role(AIFleetMissionType.FLEET_MISSION_EXPLORATION)
    productionQueue = empire.productionQueue
    queuedScoutShips=0
    for queue_index in range(0, len(productionQueue)):
        element=productionQueue[queue_index]
        if element.buildType == EnumsAI.AIEmpireProductionTypes.BT_SHIP:
            if foAI.foAIstate.get_ship_role(element.designID) == EnumsAI.AIShipRoleType.SHIP_ROLE_CIVILIAN_EXPLORATION :
                queuedScoutShips += element.remaining * element.blocksize

    milShips = MilitaryAI.num_milships
    # intent of the following calc is essentially 
    # new_scouts_needed = min(need_cap_A, need_cap_B, base_need) - already_got_or_queued
    # where need_cap_A is to help prevent scouting needs from swamping military needs, and 
    # need_cap_B is to help regulate investment into scouting while the empire is small.
    # These caps could perhaps instead be tied more directly to military priority and 
    # total empire production.
    scoutsNeeded = max(0, min( 4+int(milShips/5), 4+int(fo.currentTurn()/50) , 2+ numUnexploredSystems**0.5 ) - numScouts - queuedScoutShips )
    explorationPriority = int(40*scoutsNeeded)

    print
    print "Number of Scouts : " + str(numScouts)
    print "Number of Unexplored systems: " + str(numUnexploredSystems)
    print "military size: ", milShips
    print "Priority for scouts : " + str(explorationPriority)

    return explorationPriority
Example #21
0
    def __cleanExplorableSystems(self, startSystemID):
        "cleanup of all explorable systems"

        universe = fo.getUniverse()
        systemIDs = universe.systemIDs
        empireID = fo.empireID()
        empire = fo.getEmpire()

        for systemID in systemIDs:
            system = universe.getSystem(systemID)
            if not system: continue

            #print "system with id: " + str(systemID)

            if (empire.hasExploredSystem(systemID)):
                self.addExplorableSystem(AIExplorableSystemType.EXPLORABLE_SYSTEM_EXPLORED, systemID)
                self.removeExplorableSystem(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED, systemID)
                #print "    has been explored"
                continue
            if (startSystemID == -1 or not universe.systemsConnected(systemID, startSystemID, empireID)):
                for explorableSystemsType in EnumsAI.getAIExplorableSystemTypes():
                    self.removeExplorableSystem(explorableSystemsType, systemID)
                #print "    is not connected to system with id: " + str(startSystemID)
                continue
            explorableSystemsType = self.getExplorableSystem(systemID)
            if (explorableSystemsType == AIExplorableSystemType.EXPLORABLE_SYSTEM_VISIBLE):
                #print "    is already explored system target"
                continue
            #print "    is now an unexplored system"
            self.addExplorableSystem(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED, systemID)
Example #22
0
def startNewGame(aggression_input=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring new game start message."
        return

    turn_timer.start("Server Processing")

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

    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression_trait.key, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Example #23
0
def prepareForSave():  # pylint: disable=invalid-name
    """Called by client when the game is about to be saved, to let the Python AI know it should save any AI state
    information, such as plans or knowledge about the game from previous turns,
    in the state string so that they can be restored if the game is loaded."""
    empire = fo.getEmpire()
    if empire is None:
        print "This client has no empire. Doing nothing to prepare for save."
        return

    if empire.eliminated:
        info("This empire has been eliminated. Save info request")
        return

    info("Preparing for game save by serializing state")

    # serialize (convert to string) global state dictionary and send to AI client to be stored in save file
    try:
        dump_string = pickle.dumps(foAIstate)
        print "foAIstate pickled to string, about to send to server"
        fo.setSaveStateString(dump_string)
    except:
        error(
            "foAIstate unable to pickle save-state string; "
            "the save file should be playable but the AI may have a different aggression.",
            exc_info=True)
Example #24
0
def can_travel_to_system_and_return_to_resupply(fleet_id, from_system_target, to_system_target):
    """
    Filter systems where fleet can travel from starting system. # TODO rename function
    
    :param fleet_id:
    :type fleet_id: int
    :param from_system_target:
    :type from_system_target: universe_object.System
    :param to_system_target:
    :type to_system_target: universe_object.System
    :return:
    :rtype: list
    """
    system_targets = []
    if not from_system_target.id == to_system_target.id:
        fleet_supplyable_system_ids = fo.getEmpire().fleetSupplyableSystemIDs
        fuel = int(FleetUtilsAI.get_fuel(fleet_id))  # int to get actual number of jumps
        max_fuel = int(FleetUtilsAI.get_max_fuel(fleet_id))
        # try to find path without going resupply first
        supply_system_target = get_nearest_supplied_system(to_system_target.id)
        system_targets = __find_path_with_fuel_to_system_with_possible_return(from_system_target, to_system_target, system_targets, fleet_supplyable_system_ids, max_fuel, fuel, supply_system_target)
        # resupply in system first is required to find path
        if from_system_target.id not in fleet_supplyable_system_ids and not system_targets:
            # add supply system to visit
            from_system_target = get_nearest_supplied_system(from_system_target.id)
            system_targets.append(from_system_target)
            # find path from supplied system to wanted system
            system_targets = __find_path_with_fuel_to_system_with_possible_return(from_system_target, to_system_target, system_targets, fleet_supplyable_system_ids, max_fuel, max_fuel, supply_system_target)
    return system_targets
Example #25
0
def calculateIndustryPriority():
    "calculates the demand for industry"

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

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


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

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

    return industryPriority
Example #26
0
def calculateResearchPriority():
    "calculates the AI empire's demand for research"

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

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

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


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

    return researchPriority
Example #27
0
def calculateExplorationPriority():
    "calculates the demand for scouts by unexplored systems"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    numUnexploredSystems =  len( ExplorationAI.__borderUnexploredSystemIDs   )  #len(foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED))
    scoutIDs = ExplorationAI.currentScoutFleetIDs #    FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_EXPLORATION)
    numScouts = len(scoutIDs)
    productionQueue = empire.productionQueue
    queuedScoutShips=0
    for queue_index  in range(0,  len(productionQueue)):
        element=productionQueue[queue_index]
        if element.buildType == AIEmpireProductionTypes.BT_SHIP:
             if foAI.foAIstate.getShipRole(element.designID) ==       AIShipRoleType.SHIP_ROLE_CIVILIAN_EXPLORATION  :
                 queuedScoutShips +=element.remaining

    
    explorationPriority = 95*math.ceil(  math.sqrt(max(0,  (numUnexploredSystems - (numScouts+queuedScoutShips)) / (numUnexploredSystems +0.001) )))

    print ""
    print "Number of Scouts            : " + str(numScouts)
    print "Number of Unexplored systems: " + str(numUnexploredSystems)
    print "Priority for scouts         : " + str(explorationPriority)

    return explorationPriority
Example #28
0
def canTravelToSystemAndReturnToResupply(fleetID, fromSystemAITarget, toSystemAITarget, empireID,  verbose=False):
    "check if fleet can travel from starting system to wanted system"

    systemAITargets = []
    if not fromSystemAITarget.getTargetID() == toSystemAITarget.getTargetID:
        # get supplyable systems
        empire = fo.getEmpire()
        fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
        # get current fuel and max fuel
        universe = fo.getUniverse()
        fleet = universe.getFleet(fleetID)
        maxFuel = int(fleet.maxFuel)
        fuel = int(fleet.fuel)
        if verbose:
            print "   fleet ID %d  has  %.1f fuel  to get from %s    to  %s"%(fleetID,  fuel,  fromSystemAITarget,  toSystemAITarget )

        # try to find path without going resupply first
        supplySystemAITarget = getNearestSuppliedSystem(toSystemAITarget.getTargetID(), empireID)
        systemAITargets = __findPathWithFuelToSystemWithPossibleReturn(fromSystemAITarget, toSystemAITarget, empireID, systemAITargets, fleetSupplyableSystemIDs, maxFuel, fuel, supplySystemAITarget)
        # resupply in system first is required to find path
        if not(fromSystemAITarget.getTargetID() in fleetSupplyableSystemIDs) and len(systemAITargets) == 0:
            # add supply system to visit
            fromSystemAITarget = getNearestSuppliedSystem(fromSystemAITarget.getTargetID(), empireID)
            systemAITargets.append(fromSystemAITarget)
            # find path from supplied system to wanted system
            systemAITargets = __findPathWithFuelToSystemWithPossibleReturn(fromSystemAITarget, toSystemAITarget, empireID, systemAITargets, fleetSupplyableSystemIDs, maxFuel, maxFuel, supplySystemAITarget)

    return systemAITargets
Example #29
0
def prepareForSave():  # pylint: disable=invalid-name
    """Called by client when the game is about to be saved, to let the Python AI know it should save any AI state
    information, such as plans or knowledge about the game from previous turns,
    in the state string so that they can be restored if the game is loaded."""
    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Doing nothing to prepare for save.")
        return

    if empire.eliminated:
        info("This empire has been eliminated. Save info request")
        return

    info("Preparing for game save by serializing state")

    # serialize (convert to string) global state dictionary and send to AI client to be stored in save file
    import savegame_codec
    try:
        dump_string = savegame_codec.build_savegame_string()
        fo.setSaveStateString(dump_string)
    except Exception as e:
        error("Failed to encode the AIstate as save-state string. "
              "The resulting save file should be playable but the AI "
              "may have a different aggression. The error raised was: %s"
              % e, exc_info=True)
Example #30
0
def getCapitalID():
    "return planetID of empire capital"

    empire = fo.getEmpire()
    capitalID = empire.capitalID

    return capitalID
Example #31
0
    def can_issue_order(self, verbose=False):
        if not super(OrderMove, self).can_issue_order(verbose=verbose):
            return False
        # TODO: figure out better way to have invasions (& possibly colonizations) require visibility on target without needing visibility of all intermediate systems
        # if False and main_mission_type not in [AIFleetMissionType.FLEET_MISSION_ATTACK,  # TODO: consider this later
        #                                      AIFleetMissionType.FLEET_MISSION_MILITARY,
        #                                      AIFleetMissionType.FLEET_MISSION_SECURE,
        #                                      AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN,
        #                                      AIFleetMissionType.FLEET_MISSION_EXPLORATION]:
        #     if not universe.getVisibility(target_id, foAI.foAIstate.empireID) >= fo.visibility.partial:
        #         #if not target_id in interior systems
        #         foAI.foAIstate.needsEmergencyExploration.append(fleet.systemID)
        #         return False
        system_id = self.fleet.get_system().id
        if system_id == self.target.get_system().id:
            return True  # TODO: already there, but could consider retreating

        fleet_rating = foAI.foAIstate.get_rating(self.fleet.id).get('overall', 0)
        target_sys_status = foAI.foAIstate.systemStatus.get(self.target.id, {})
        f_threat = target_sys_status.get('fleetThreat', 0)
        m_threat = target_sys_status.get('monsterThreat', 0)
        p_threat = target_sys_status.get('planetThreat', 0)
        threat = f_threat + m_threat + p_threat
        safety_factor = MilitaryAI.get_safety_factor()
        universe = fo.getUniverse()
        if fleet_rating >= safety_factor * threat:
            return True
        elif not p_threat and self.target.id in fo.getEmpire().supplyUnobstructedSystems:
                    return True
        else:
            sys1 = universe.getSystem(system_id)
            sys1_name = sys1 and sys1.name or "unknown"
            targ1 = self.target.get_system()
            targ1_name = (targ1 and targ1.get_object().name) or "unknown"
            # following line was poor because AIstate.militaryFleetIDs only covers fleets without current missions
            # my_other_fleet_rating = sum([foAI.foAIstate.fleetStatus.get(fleet_id, {}).get('rating', 0) for fleet_id in foAI.foAIstate.militaryFleetIDs if ( foAI.foAIstate.fleetStatus.get(fleet_id, {}).get('sysID', -1) == thisSystemID ) ])
            # myOtherFleetsRatings = [foAI.foAIstate.fleetStatus.get(fid, {}).get('rating', {}) for fid in foAI.foAIstate.systemStatus.get(target_id, {}).get('myfleets', [])]
            # my_other_fleet_rating = sum([foAI.foAIstate.fleetStatus.get(fid, {}).get('rating', 0) for fid in foAI.foAIstate.systemStatus.get( target_id, {}).get('myfleets', []) ])
            my_other_fleet_rating = foAI.foAIstate.systemStatus.get(self.target.id, {}).get('myFleetRating', 0)  # TODO: adjust calc for any departing fleets
            is_military = foAI.foAIstate.get_fleet_role(self.fleet.id) == AIFleetMissionType.FLEET_MISSION_MILITARY
            if ((my_other_fleet_rating > 3 * safety_factor * threat) or
                        (is_military and my_other_fleet_rating + fleet_rating > safety_factor * threat) or
                        (is_military and my_other_fleet_rating + fleet_rating > 0.8 * safety_factor * threat and fleet_rating > 0.2 * threat)):
                if verbose:
                    print "\tAdvancing fleet %d (rating %d) at system %d (%s) into system %d (%s) with threat %d because of sufficient empire fleet strength already at destination" % (
                        self.fleet.id, fleet_rating, system_id, sys1_name, self.target.id, targ1_name, threat)
                return True
            elif threat == p_threat and not self.fleet.get_object().aggressive and not my_other_fleet_rating and not target_sys_status.get('localEnemyFleetIDs', [-1]):
                if verbose:
                    print ("\tAdvancing fleet %d (rating %d) at system %d (%s) into system %d (%s) with planet threat %d because nonaggressive" +
                           " and no other fleets present to trigger combat") % (self.fleet.id, fleet_rating, system_id, sys1_name, self.target.id, targ1_name, threat)
                return True
            else:
                if verbose:
                    print "\tHolding fleet %d (rating %d) at system %d (%s) before travelling to system %d (%s) with threat %d" % (self.fleet.id, fleet_rating, system_id, sys1_name, self.target.id, targ1_name, threat)
                needs_vis = foAI.foAIstate.misc.setdefault('needs_vis', [])
                if self.target.id not in needs_vis:
                    needs_vis.append(self.target.id)
                return False
        return True
Example #32
0
def setCapitalIDResourceFocus():
    "set resource focus of CapitalID planet"

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    empirePlanetIDs = PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    capitalID = PlanetUtilsAI.getCapital()
    topPriority = topResourcePriority()

    if topPriority == AIPriorityType.PRIORITY_RESOURCE_GROWTH:
        newFocus = AIFocusType.FOCUS_GROWTH
        for planetID in empirePlanetIDs:
            planet = universe.getPlanet(planetID)
            focus = newFocus
            if planetID == capitalID and focus in planet.availableFoci:
                fo.issueChangeFocusOrder(planetID, focus)
    elif topPriority == AIPriorityType.PRIORITY_RESOURCE_PRODUCTION:
        newFocus = AIFocusType.FOCUS_INDUSTRY
        for planetID in empirePlanetIDs:
            planet = universe.getPlanet(planetID)
            focus = newFocus
            if planetID == capitalID and focus in planet.availableFoci:
                fo.issueChangeFocusOrder(planetID, focus)
    elif topPriority == AIPriorityType.PRIORITY_RESOURCE_RESEARCH:
        newFocus = AIFocusType.FOCUS_RESEARCH
        for planetID in empirePlanetIDs:
            planet = universe.getPlanet(planetID)
            focus = newFocus
            if planetID == capitalID and focus in planet.availableFoci:
                fo.issueChangeFocusOrder(planetID, focus)
Example #33
0
def generateDefaultResearchOrders():
    "generate default research orders"

    empire = fo.getEmpire()
    totalRP = empire.resourceProduction(fo.resourceType.research)

    # get all usable researchable techs not already completed or queued for research
    completedTechs = getCompletedTechs()
    possibleProjects = getPossibleProjects()
    researchQueue = empire.researchQueue
    researchQueueList = getResearchQueueTechs ()
    possibleResearchProjects = (set(possibleProjects)-(set(completedTechs)|set(researchQueueList)))

    print "Techs in possibleResearchProjects list after enqueues to Research Queue:"
    for techname in possibleResearchProjects:
        print "    " + techname
    print ""

    # store projects mapped to their costs, so they can be sorted by that cost
    projectsDict = dict()
    for name in possibleResearchProjects:
        projectsDict[name] = fo.getTech(name).researchCost(empire.empireID)

    # iterate through techs in order of cost
    print "enqueuing techs.  already spent RP: " + str(spentRP()) + "  total RP: " + str(totalRP)
    for name, cost in sorted(projectsDict.items(), key=lambda(k, v):(v, k)):
        # abort if no RP left
        if spentRP() >= totalRP:
            break

        # add tech to queue
        fo.issueEnqueueTechOrder(name, -1)
        print "    enqueued tech " + name + "  :  cost: " + str(cost) + "RP"
    print ""
Example #34
0
def _calculate_exploration_priority():
    """Calculates the demand for scouts by unexplored systems."""
    empire = fo.getEmpire()
    num_unexplored_systems = len(ExplorationAI.borderUnexploredSystemIDs)
    num_scouts = sum([foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) for fid in FleetUtilsAI.get_empire_fleet_ids_by_role(
        MissionType.EXPLORATION)])
    production_queue = empire.productionQueue
    queued_scout_ships = 0
    for queue_index in range(0, len(production_queue)):
        element = production_queue[queue_index]
        if element.buildType == EmpireProductionTypes.BT_SHIP:
            if foAI.foAIstate.get_ship_role(element.designID) == ShipRoleType.CIVILIAN_EXPLORATION:
                queued_scout_ships += element.remaining * element.blocksize

    mil_ships = MilitaryAI.get_num_military_ships()
    # intent of the following calc is essentially
    # new_scouts_needed = min(need_cap_A, need_cap_B, base_need) - already_got_or_queued
    # where need_cap_A is to help prevent scouting needs from swamping military needs, and
    # need_cap_B is to help regulate investment into scouting while the empire is small.
    # These caps could perhaps instead be tied more directly to military priority and
    # total empire production.
    desired_number_of_scouts = int(min(4 + mil_ships/5, 4 + fo.currentTurn()/50.0, 2 + num_unexplored_systems**0.5))
    scouts_needed = max(0, desired_number_of_scouts - (num_scouts + queued_scout_ships))
    exploration_priority = int(40 * scouts_needed)

    print
    print "Number of Scouts: %s" % num_scouts
    print "Number of Unexplored systems: %s" % num_unexplored_systems
    print "Military size: %s" % mil_ships
    print "Priority for scouts: %s" % exploration_priority

    return exploration_priority
Example #35
0
 def print_resource_ai_footer():
     empire = fo.getEmpire()
     pp, rp = empire.productionPoints, empire.resourceProduction(fo.resourceType.research)
     # Next string used in charts. Don't modify it!
     print "Current Output (turn %4d) RP/PP : %.2f ( %.1f / %.1f )" % (fo.currentTurn(), rp / (pp + 0.0001), rp, pp)
     print "------------------------"
     print "ResourcesAI Time Requirements:"
Example #36
0
def resumeLoadedGame(saved_state_string):  # pylint: disable=invalid-name
    """Called by client to when resume a loaded game."""
    if fo.getEmpire().eliminated:
        print "This empire has been eliminated. Ignoring resume loaded game."
        return
    turn_timer.start("Server Processing")

    global foAIstate
    print "Resuming loaded game"
    try:
        # loading saved state
        # pre load code
        foAIstate = pickle.loads(saved_state_string)
    except Exception as e:
        # assigning new state
        foAIstate = AIstate.AIstate(fo.aggression.aggressive)
        foAIstate.session_start_cleanup()
        print_error("Fail to load aiState form saved game: %s" % e)

    aggression_trait = foAIstate.character.get_trait(Aggression)
    diplomatic_corp_configs = {fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
                               fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp}
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(aggression_trait.key, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()
Example #37
0
def calculateColonisationPriority():
    "calculates the demand for colony ships by colonisable planets"
    global allottedColonyTargets
    totalPP=fo.getEmpire().productionPoints
    colonyCost=120*(1+ 0.06*len( list(AIstate.popCtrIDs) ))
    turnsToBuild=8#TODO: check for susp anim pods, build time 10
    allottedPortion = [0.4,  0.5][ random.choice([0, 1]) ]    #fo.empireID() % 2
    if ( foAI.foAIstate.getPriority(EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_COLONISATION) 
            > 2 * foAI.foAIstate.getPriority(EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_MILITARY)):
        allottedPortion *= 1.5
    #allottedColonyTargets = 1+ int(fo.currentTurn()/50)
    allottedColonyTargets = 1 + int( totalPP*turnsToBuild*allottedPortion/colonyCost)

    numColonisablePlanetIDs = len(    [  pid   for (pid,  (score, specName) ) in  foAI.foAIstate.colonisablePlanetIDs if score > 60 ][:allottedColonyTargets+2] )
    if (numColonisablePlanetIDs == 0): return 1

    colonyshipIDs = FleetUtilsAI.getEmpireFleetIDsByRole(EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION)
    numColonyships = len(FleetUtilsAI.extractFleetIDsWithoutMissionTypes(colonyshipIDs))
    colonisationPriority = 121 * (1+numColonisablePlanetIDs - numColonyships) / (numColonisablePlanetIDs+1)

    # print ""
    # print "Number of Colony Ships        : " + str(numColonyships)
    # print "Number of Colonisable planets : " + str(numColonisablePlanetIDs)
    # print "Priority for colony ships     : " + str(colonisationPriority)

    if colonisationPriority < 1: return 1

    return colonisationPriority
Example #38
0
def generateOrders():
    empire = fo.getEmpire()
    print "Empire:  " + empire.name + " TURN: " + str(fo.currentTurn())
    print "Capital: " + str(empire.capitalID)

    # turn cleanup
    splitFleet()

    identifyShipDesigns()
    identifyFleetsRoles()
    foAIstate.clean(ExplorationAI.getHomeSystemID(), FleetUtilsAI.getEmpireFleetIDs())
    # ...missions
    # ...demands/priorities

    # call AI modules
    PriorityAI.calculatePriorities()
    ExplorationAI.assignScoutsToExploreSystems()
    ColonisationAI.assignColonyFleetsToColonise()
    InvasionAI.assignInvasionFleetsToInvade()
    FleetUtilsAI.generateAIFleetOrdersForAIFleetMissions()
    FleetUtilsAI.issueAIFleetOrdersForAIFleetMissions()
    ResearchAI.generateResearchOrders()
    ProductionAI.generateProductionOrders()
    ResourcesAI.generateResourcesOrders()    

    foAIstate.afterTurnCleanup()
    fo.doneTurn()
Example #39
0
def generateOrders():
    print ("Genearting Orders")
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    planetID = empire.capitalID
    planet = universe.getPlanet(planetID)
    print "EmpireID:    " + str(empire.empireID) + " Name: " + empire.name + " Turn: " + str(fo.currentTurn())
    print "CapitalID: " + str(planetID) + " Name: " + planet.name + " Species: " + planet.speciesName 

    # turn cleanup
    splitFleet()

    identifyShipDesigns()
    identifyFleetsRoles()
    foAIstate.clean(ExplorationAI.getHomeSystemID(), FleetUtilsAI.getEmpireFleetIDs())
    # ...missions
    # ...demands/priorities

    print("Calling AI Modules")

    # call AI modules
    PriorityAI.calculatePriorities()
    ExplorationAI.assignScoutsToExploreSystems()
    ColonisationAI.assignColonyFleetsToColonise()
    InvasionAI.assignInvasionFleetsToInvade()
    MilitaryAI.assignMilitaryFleetsToSystems()
    FleetUtilsAI.generateAIFleetOrdersForAIFleetMissions()
    FleetUtilsAI.issueAIFleetOrdersForAIFleetMissions()
    ResearchAI.generateResearchOrders()
    ProductionAI.generateProductionOrders()
    ResourcesAI.generateResourcesOrders()    

    foAIstate.afterTurnCleanup()
    fo.doneTurn()
Example #40
0
def calculateExplorationPriority():
    """calculates the demand for scouts by unexplored systems"""
    global scoutsNeeded

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    numUnexploredSystems = len( ExplorationAI.borderUnexploredSystemIDs )  #len(foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED))
    numScouts = sum( [ foAI.foAIstate.fleetStatus.get(fid, {}).get('nships', 0) for fid in ExplorationAI.currentScoutFleetIDs] ) # FleetUtilsAI.get_empire_fleet_ids_by_role(AIFleetMissionType.FLEET_MISSION_EXPLORATION)
    productionQueue = empire.productionQueue
    queuedScoutShips=0
    for queue_index in range(0, len(productionQueue)):
        element=productionQueue[queue_index]
        if element.buildType == EnumsAI.AIEmpireProductionTypes.BT_SHIP:
            if foAI.foAIstate.get_ship_role(element.designID) == EnumsAI.AIShipRoleType.SHIP_ROLE_CIVILIAN_EXPLORATION :
                queuedScoutShips += element.remaining * element.blocksize

    milShips = MilitaryAI.num_milships
    scoutsNeeded = max(0, min( 4+int(milShips/5), 4+int(fo.currentTurn()/50) , 2+ numUnexploredSystems**0.5 ) - numScouts - queuedScoutShips )
    explorationPriority = int(40*scoutsNeeded)

    print
    print "Number of Scouts : " + str(numScouts)
    print "Number of Unexplored systems: " + str(numUnexploredSystems)
    print "military size: ", milShips
    print "Priority for scouts : " + str(explorationPriority)

    return explorationPriority
Example #41
0
def getCapital(): # if no current capital returns planet with biggest pop
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    if empire == None:
        print "Danger Danger! FO can't find an empire for me!!!!"
        return None
    empireID = empire.empireID
    capitalID = empire.capitalID
    homeworld = universe.getPlanet(capitalID)
    if homeworld:
        if homeworld.owner==empireID:
            return capitalID
        else:
            print "Nominal Capitol %s does not appear to be owned by empire %d  %s"%(homeworld.name,  empireID,  empire.name)
    #exploredSystemIDs = empire.exploredSystemIDs
    #exploredPlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(exploredSystemIDs)
    empireOwnedPlanetIDs = getOwnedPlanetsByEmpire(universe.planetIDs, empireID)
    peopledPlanets = getPopulatedPlanetIDs(  empireOwnedPlanetIDs)
    if not peopledPlanets:
        if empireOwnedPlanetIDs:
            return empireOwnedPlanetIDs[0]
        else:
            return None
    popMap = []
    for planetID in peopledPlanets:
        popMap.append( ( universe.getPlanet(planetID).currentMeterValue(fo.meterType.population) ,  planetID) )
    popMap.sort()
    return popMap[-1][-1]
Example #42
0
def resumeLoadedGame(saved_state_string):  # pylint: disable=invalid-name
    """Called by client to when resume a loaded game."""
    debug("Resuming loaded game")

    if saved_state_string == "NO_STATE_YET" and fo.currentTurn() == 1:
        info("AI given uninitialized state-string to resume from on turn 1.")
        info(
            "Assuming post-universe-generation autosave before any orders were sent "
            "and behaving as if a new game was started.")
        return startNewGame()

    if fo.getEmpire() is None:
        fatal(
            "This client has no empire. Doing nothing to resume loaded game.")
        return

    if fo.getEmpire().eliminated:
        info("This empire has been eliminated. Ignoring resume loaded game.")
        return

    aistate = None
    if saved_state_string == "NOT_SET_BY_CLIENT_TYPE":
        info("AI assigned to empire previously run by human.")
        chat_human(
            "We have been assigned an empire previously run by a human player. We can manage this."
        )
    elif saved_state_string == "":
        error(
            "AI given empty state-string to resume from. "
            "AI can continue but behaviour may be different from the previous session."
        )
    else:
        try:
            # loading saved state
            aistate = load_aistate(saved_state_string)
        except Exception as e:
            error(
                "Failed to load the AIstate from the savegame: %s"
                " AI can continue but behaviour may be different from the previous session.",
                e,
                exc_info=True,
            )
    if aistate is None:
        info("Creating new ai state due to failed load.")
        aistate = create_new_aistate(_choose_aggression())
    aistate.session_start_cleanup()
    _pre_game_start(fo.getEmpire().empireID)
Example #43
0
def resumeLoadedGame(saved_state_string):  # pylint: disable=invalid-name
    """Called by client to when resume a loaded game."""
    if fo.getEmpire() is None:
        print "This client has no empire. Doing nothing to resume loaded game."
        return

    if fo.getEmpire().eliminated:
        print "This empire has been eliminated. Ignoring resume loaded game."
        return
    turn_timer.start("Server Processing")

    global foAIstate
    print "Resuming loaded game"
    if not saved_state_string:
        error(
            "AI given empty state-string to resume from; this is expected if the AI is assigned to an empire "
            "previously run by a human, but is otherwise an error. AI will be set to Aggressive."
        )
        foAIstate = AIstate.AIstate(fo.aggression.aggressive)
        foAIstate.session_start_cleanup()
    else:
        import savegame_codec
        try:
            # loading saved state
            foAIstate = savegame_codec.load_savegame_string(saved_state_string)
        except Exception as e:
            # assigning new state
            foAIstate = AIstate.AIstate(fo.aggression.aggressive)
            foAIstate.session_start_cleanup()
            error(
                "Failed to load the AIstate from the savegame. The AI will"
                " play with a fresh AIstate instance with aggression level set"
                " to 'aggressive'. The behaviour of the AI may be different"
                " than in the original session. The error raised was: %s" % e,
                exc_info=True)

    aggression_trait = foAIstate.character.get_trait(Aggression)
    diplomatic_corp_configs = {
        fo.aggression.beginner: DiplomaticCorp.BeginnerDiplomaticCorp,
        fo.aggression.maniacal: DiplomaticCorp.ManiacalDiplomaticCorp
    }
    global diplomatic_corp
    diplomatic_corp = diplomatic_corp_configs.get(
        aggression_trait.key, DiplomaticCorp.DiplomaticCorp)()
    TechsListsAI.test_tech_integrity()

    debug('Size of already issued orders: ' + str(fo.getOrders().size))
Example #44
0
    def _check_abort_mission(self, fleet_order: AIFleetOrder):
        """checks if current mission (targeting a planet) should be aborted"""
        planet_stealthed = False
        target_is_planet = fleet_order.target and isinstance(
            fleet_order.target, TargetPlanet)
        planet = None
        if target_is_planet:
            planet = fleet_order.target.get_object()
            # Check visibility prediction, but if somehow still have current visibility, don't
            # abort the mission yet
            if not EspionageAI.colony_detectable_by_empire(
                    planet.id, empire=fo.empireID()):
                if get_partial_visibility_turn(planet.id) == fo.currentTurn():
                    debug(
                        "EspionageAI predicts planet id %d to be stealthed" %
                        planet.id +
                        ", but somehow have current visibity anyway, so won't trigger mission abort"
                    )
                else:
                    debug(
                        "EspionageAI predicts we can no longer detect %s, will abort mission"
                        % fleet_order.target)
                    planet_stealthed = True
        if target_is_planet and not planet_stealthed:
            # TBD use fleet_order.is_valid or add fleet_order.should_abort
            if isinstance(fleet_order, OrderColonize):
                if planet.initialMeterValue(fo.meterType.population) == 0 and (
                        planet.ownedBy(fo.empireID()) or planet.unowned):
                    return False
            elif isinstance(fleet_order, OrderOutpost):
                if planet.unowned:
                    return False
            elif isinstance(fleet_order, OrderInvade):
                if planet.owner == fo.getEmpire().empireID:
                    debug(
                        f"Abandoning invasion for {planet}, it already belongs to us"
                    )
                    return True
                if planet.currentMeterValue(fo.meterType.maxShield):
                    military_support_fleets = MilitaryAI.get_military_fleets_with_target_system(
                        planet.systemID)
                    if not military_support_fleets:
                        # Maybe try again later...
                        debug(
                            f"Abandoning Invasion mission for {planet} because target has nonzero max shields "
                            f"and there is no military fleet assigned to secure the target system."
                        )
                        return True
                return False
            else:
                return False

        # canceling fleet orders
        debug("   %s" % fleet_order)
        debug(
            "Fleet %d had a target planet that is no longer valid for this mission; aborting."
            % self.fleet.id)
        FleetUtilsAI.split_fleet(self.fleet.id)
        return True
Example #45
0
    def __init__(self, aggression):
        # Do not allow to create AIstate instances with an invalid version number.
        if not hasattr(AIstate, 'version'):
            raise ConversionError("AIstate must have an integer version attribute for savegame compatibility")
        if not isinstance(AIstate.version, int):
            raise ConversionError("Version attribute of AIstate must be an integer!")
        if AIstate.version < 0:
            raise ConversionError("AIstate savegame compatibility version must be a positive integer!")
            
        # need to store the version explicitly as the class variable "version" is only stored in the 
        # self.__class__.__dict__ while we only pickle the object (i.e. self.__dict__ )
        self.version = AIstate.version
        
        # Debug info
        # unique id for game
        self.uid = self.generate_uid(first=True)
        # unique ids for turns.  {turn: uid}
        self.turn_uids = {}

        self._aggression = aggression

        # 'global' (?) variables
        self.colonisablePlanetIDs = odict()
        self.colonisableOutpostIDs = odict()  #
        self.__aiMissionsByFleetID = {}
        self.__shipRoleByDesignID = {}
        self.__fleetRoleByID = {}
        self.diplomatic_logs = {}
        self.__priorityByType = {}

        # initialize home system knowledge
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        self.empireID = empire.empireID
        homeworld = universe.getPlanet(empire.capitalID)
        self.__origin_home_system_id = homeworld.systemID if homeworld else INVALID_ID
        self.visBorderSystemIDs = {self.__origin_home_system_id}
        self.visInteriorSystemIDs = set()
        self.exploredSystemIDs = set()
        self.unexploredSystemIDs = {self.__origin_home_system_id}
        self.fleetStatus = {}  # keys: 'sysID', 'nships', 'rating'
        # systemStatus keys: 'name', 'neighbors' (sysIDs), '2jump_ring' (sysIDs), '3jump_ring', '4jump_ring', 'enemy_ship_count'
        # 'fleetThreat', 'planetThreat', 'monsterThreat' (specifically, immobile nonplanet threat), 'totalThreat', 'localEnemyFleetIDs',
        # 'neighborThreat', 'max_neighbor_threat', 'jump2_threat' (up to 2 jumps away), 'jump3_threat', 'jump4_threat', 'regional_threat'
        # 'myDefenses' (planet rating), 'myfleets', 'myFleetsAccessible'(not just next desitination), 'myFleetRating'
        # 'my_neighbor_rating' (up to 1 jump away), 'my_jump2_rating', 'my_jump3_rating', my_jump4_rating'
        # 'local_fleet_threats', 'regional_fleet_threats' <== these are only for mobile fleet threats
        self.systemStatus = {}
        self.needsEmergencyExploration = []
        self.newlySplitFleets = {}
        self.militaryRating = 0
        self.shipCount = 4
        self.misc = {}
        self.qualifyingColonyBaseTargets = {}
        self.qualifyingOutpostBaseTargets = {}
        self.qualifyingTroopBaseTargets = {}
        self.__empire_standard_enemy = CombatRatingsAI.default_ship_stats().get_stats(hashable=True)  # TODO: track on a per-empire basis
        self.empire_standard_enemy_rating = 0  # TODO: track on a per-empire basis
        self.character = create_character(aggression, self.empireID)
Example #46
0
def calculateColonisationPriority():
    """calculates the demand for colony ships by colonisable planets"""
    global allottedColonyTargets, colony_growth_barrier
    enemies_sighted = foAI.foAIstate.misc.get('enemies_sighted', {})
    galaxy_is_sparse = ColonisationAI.galaxy_is_sparse()
    total_pp = fo.getEmpire().productionPoints
    num_colonies = len(list(AIstate.popCtrIDs))
    # significant growth barrier for low aggression, negligible for high aggression
    colony_growth_barrier = 2 + (
        (0.5 + foAI.foAIstate.aggression)**2) * fo.currentTurn() / 50.0
    colonyCost = AIDependencies.COLONY_POD_COST * (
        1 + AIDependencies.COLONY_POD_UPKEEP * num_colonies)
    turnsToBuild = 8  # TODO: check for susp anim pods, build time 10
    mil_prio = foAI.foAIstate.get_priority(
        EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_MILITARY)
    allottedPortion = ([[[0.6, 0.8], [0.3, 0.4]], [[0.8, 0.9], [
        0.3, 0.4
    ]]][galaxy_is_sparse][any(enemies_sighted)][fo.empireID() % 2])
    #if ( foAI.foAIstate.get_priority(EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_COLONISATION)
    # > 2 * foAI.foAIstate.get_priority(EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_MILITARY)):
    # allottedPortion *= 1.5
    if mil_prio < 100:
        allottedPortion *= 2
    elif mil_prio < 200:
        allottedPortion *= 1.5
    elif fo.currentTurn() > 100:
        allottedPortion *= 0.75**(num_colonies / 10.0)
    #allottedColonyTargets = 1+ int(fo.currentTurn()/50)
    allottedColonyTargets = 1 + int(
        total_pp * turnsToBuild * allottedPortion / colonyCost)
    outpost_prio = foAI.foAIstate.get_priority(
        EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_OUTPOST)
    # if have any outposts to build, don't build colony ships TODO: make more complex assessment
    if outpost_prio > 0 or num_colonies > colony_growth_barrier:
        return 0.0

    if num_colonies > colony_growth_barrier:
        return 0.0
    numColonisablePlanetIDs = len([
        pid
        for (pid, (score, _)) in foAI.foAIstate.colonisablePlanetIDs.items()
        if score > 60
    ][:allottedColonyTargets + 2])
    if numColonisablePlanetIDs == 0: return 1

    colonyshipIDs = FleetUtilsAI.get_empire_fleet_ids_by_role(
        EnumsAI.AIFleetMissionType.FLEET_MISSION_COLONISATION)
    numColonyships = len(
        FleetUtilsAI.extract_fleet_ids_without_mission_types(colonyshipIDs))
    colonisationPriority = 60 * (1 + numColonisablePlanetIDs - numColonyships
                                 ) / (numColonisablePlanetIDs + 1)

    # print
    # print "Number of Colony Ships : " + str(numColonyships)
    # print "Number of Colonisable planets : " + str(numColonisablePlanetIDs)
    # print "Priority for colony ships : " + str(colonisationPriority)

    if colonisationPriority < 1: return 0
    return colonisationPriority
Example #47
0
    def print_resources_priority():
        """Calculate top resource priority."""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire()
        debug("Resource Priorities:")
        resource_priorities = {}
        aistate = get_aistate()
        for priority_type in get_priority_resource_types():
            resource_priorities[priority_type] = aistate.get_priority(
                priority_type)

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

        # what is the focus of available resource centers?
        debug("")
        warnings = {}
        foci_table = Table(
            Text("Planet"),
            Text("Size"),
            Text("Type"),
            Text("Focus"),
            Text("Species"),
            Text("Pop"),
            table_name="Planetary Foci Overview Turn %d" % fo.currentTurn(),
        )
        for pid in empire_planet_ids:
            planet = universe.getPlanet(pid)
            population = planet.currentMeterValue(fo.meterType.population)
            max_population = planet.currentMeterValue(
                fo.meterType.targetPopulation)
            if max_population < 1 and population > 0:
                warnings[planet.name] = (population, max_population)
            foci_table.add_row(
                planet,
                planet.size,
                planet.type,
                "_".join(str(planet.focus).split("_")[1:])[:8],
                planet.speciesName,
                "%.1f/%.1f" % (population, max_population),
            )
        foci_table.print_table(info)
        debug(
            "Empire Totals:\nPopulation: %5d \nProduction: %5d\nResearch: %5d\n",
            empire.population(),
            empire.productionPoints,
            empire.resourceProduction(fo.resourceType.research),
        )
        for name, (cp, mp) in warnings.items():
            warning(
                "Population Warning! -- %s has unsustainable current pop %d -- target %d",
                name, cp, mp)
Example #48
0
 def queued_at(self) -> List[PlanetId]:
     """
     Return list of planet ids where this building is queued.
     """
     return [
         element.locationID for element in fo.getEmpire().productionQueue
         if (element.name == self.value)
     ]
Example #49
0
def _get_policy_multiplier(stability) -> float:
    # if fo.getEmpire().policyAdopted("TECHNOCRACY") and stability >= get_named_real("PLC_TECHNOCRACY_MIN_STABILITY"):
    #     return 1.0 + get_named_real("PLC_TECHNOCRACY_TARGET_RESEARCH_PERCENT")
    if fo.getEmpire().policyAdopted(
            "TECHNOCRACY"
    ) and stability >= get_named_real("PLC_TECHNOCRACY_MIN_STABILITY"):
        return 1.0 + get_named_real("PLC_TECHNOCRACY_TARGET_RESEARCH_PERCENT")
    return 1.0
Example #50
0
def generate_default_research_order():
    """
    Generate default research orders.
    Add cheapest technology from possible researches
    until current turn point totally spent.
    """

    empire = fo.getEmpire()
    total_rp = empire.resourceProduction(fo.resourceType.research)

    # get all usable researchable techs not already completed or queued for research

    queued_techs = get_research_queue_techs()

    def is_possible(tech_name):
        return all([
            empire.getTechStatus(tech_name) == fo.techStatus.researchable,
            not tech_is_complete(tech_name),
            not exclude_tech(tech_name),
            tech_name not in queued_techs,
        ])

    # (cost, name) for all tech that possible to add to queue, cheapest last
    possible = sorted(
        [(fo.getTech(tech).researchCost(empire.empireID), tech)
         for tech in fo.techs() if is_possible(tech)],
        reverse=True,
    )

    debug("Techs in possible list after enqueues to Research Queue:")
    for _, tech in possible:
        debug("    " + tech)
    debug("")

    # iterate through techs in order of cost
    fo.updateResearchQueue()
    total_spent = fo.getEmpire().researchQueue.totalSpent
    debug("Enqueuing techs. already spent RP: %s total RP: %s", total_spent,
          total_rp)

    while total_rp > 0 and possible:
        cost, name = possible.pop()  # get chipest
        total_rp -= cost
        fo.issueEnqueueTechOrder(name, -1)
        debug("    enqueued tech %s  : cost: %s RP", name, cost)
    debug("")
Example #51
0
def get_possible_projects():
    """get possible projects"""
    preliminary_projects = []
    empire = fo.getEmpire()
    for tech_name in fo.techs():
        if empire.getTechStatus(tech_name) == fo.techStatus.researchable:
            preliminary_projects.append(tech_name)
    return set(preliminary_projects) - set(TechsListsAI.unusable_techs())
Example #52
0
def can_travel_to_system(fleet_id, from_system_target, to_system_target, ensure_return=False):
    """
    Return list systems to be visited.

    :param fleet_id:
    :param fleet_id: int
    :param from_system_target:
    :type from_system_target: universe_object.System
    :param to_system_target:
    :type to_system_target:  universe_object.System
    :param ensure_return:
    :type ensure_return: bool
    :return:
    :rtype: list
    """
    empire = fo.getEmpire()
    empire_id = empire.empireID
    fleet_supplyable_system_ids = set(empire.fleetSupplyableSystemIDs)
    # get current fuel and max fuel
    universe = fo.getUniverse()
    fleet = universe.getFleet(fleet_id)
    fuel = int(fleet.fuel)
    if fuel < 1.0 or from_system_target.id == to_system_target.id:
        return []
    if foAI.foAIstate.aggression <= fo.aggression.typical or True:  # TODO: sort out if shortestPath leaves off some intermediate destinations
        path_func = universe.leastJumpsPath
    else:
        path_func = universe.shortestPath
    start_sys_id = from_system_target.id
    target_sys_id = to_system_target.id
    if start_sys_id != -1 and target_sys_id != -1:
        short_path = list(path_func(start_sys_id, target_sys_id, empire_id))
    else:
        short_path = []
    legs = zip(short_path[:-1], short_path[1:])
    # suppliedStops = [ sid for sid in short_path if sid in fleet_supplyable_system_ids ]
    # unsupplied_stops = [sid for sid in short_path if sid not in suppliedStops ]
    unsupplied_stops = [sys_b for sys_a, sys_b in legs if ((sys_a not in fleet_supplyable_system_ids) and (sys_b not in fleet_supplyable_system_ids))]
    # print "getting path from %s to %s "%(ppstring(PlanetUtilsAI.sys_name_ids([ start_sys_id ])), ppstring(PlanetUtilsAI.sys_name_ids([ target_sys_id ])) ),
    # print " ::: found initial path %s having suppliedStops %s and unsupplied_stops %s ; tot fuel available is %.1f"%( ppstring(PlanetUtilsAI.sys_name_ids( short_path[:])), suppliedStops, unsupplied_stops, fuel)
    if False:
        if target_sys_id in fleet_supplyable_system_ids:
            print "target has FleetSupply"
        elif target_sys_id in ColonisationAI.annexable_ring1:
            print "target in Ring 1"
        elif target_sys_id in ColonisationAI.annexable_ring2:
            print "target in Ring 2, has enough aggression is ", foAI.foAIstate.aggression >= fo.aggression.typical
        elif target_sys_id in ColonisationAI.annexable_ring3:
            print "target in Ring 2, has enough aggression is ", foAI.foAIstate.aggression >= fo.aggression.aggressive
    if (not unsupplied_stops or not ensure_return or
                target_sys_id in fleet_supplyable_system_ids and len(unsupplied_stops) <= fuel or
                target_sys_id in ColonisationAI.annexable_ring1 and len(unsupplied_stops) < fuel or
                foAI.foAIstate.aggression >= fo.aggression.typical and target_sys_id in ColonisationAI.annexable_ring2 and len(unsupplied_stops) < fuel - 1 or
                foAI.foAIstate.aggression >= fo.aggression.aggressive and target_sys_id in ColonisationAI.annexable_ring3 and len(unsupplied_stops) < fuel - 2):
        return [universe_object.System(sid) for sid in short_path]
    else:
        # print " getting path from 'can_travel_to_system_and_return_to_resupply' ",
        return can_travel_to_system_and_return_to_resupply(fleet_id, from_system_target, to_system_target)
def inspect_ai_interface():
    capital_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    fleets_int_vector = universe.fleetIDs
    fleet = universe.getFleet(list(fleets_int_vector)[0])
    ship = universe.getShip(list(universe.shipIDs)[0])
    design = fo.getShipDesign(ship.designID)
    empire = fo.getEmpire()

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

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

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

    research_queue = empire.researchQueue

    fo.issueEnqueueTechOrder('SHP_WEAPON_1_2', -1)

    planet = universe.getPlanet(capital_id)

    building = list(planet.buildingIDs)[0]

    inspect(
        fo,
        universe,
        fleet,
        planet,
        universe.getSystem(planet.systemID),
        ship,
        empire,
        design,
        tech,
        tech_spec,
        fo.getFieldType('FLD_ION_STORM'),
        fo.getBuildingType('BLD_SHIPYARD_BASE'),
        fo.getGalaxySetupData(),
        fo.getHullType('SH_XENTRONIUM'),
        fo.getPartType('SR_WEAPON_1_1'),
        fo.getSpecial('MODERATE_TECH_NATIVES_SPECIAL'),
        fo.getSpecies('SP_ABADDONI'),
        fo.getTech('SHP_WEAPON_4_1'),
        fo.diplomaticMessage(1, 2, fo.diplomaticMessageType.acceptProposal),
        fleets_int_vector,
        part_type,
        prod_queue,
        prod_queue.allocatedPP,
        prod_queue[0],
        research_queue,
        research_queue[0],
        empire.getSitRep(0),
        universe.getBuilding(building),
    )
    exit(1)  # exit game to main menu no need to play anymore.
Example #54
0
def _print_systems_and_supply(system_ids):
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
    for system_id in system_ids:
        system = universe.getSystem(system_id)
        debug('  %s%s' %
              (system if system else "  S_%s<>" % system_id,
               'supplied' if system_id in fleet_supplyable_system_ids else ''))
Example #55
0
def handleDiplomaticStatusUpdate(status_update):  # pylint: disable=invalid-name
    """Called when this player receives an update about the diplomatic status between players, which may
    or may not include this player."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring diplomatic status update"
        return
    
    diplomatic_corp.handle_diplomatic_status_update(status_update)
Example #56
0
def handleDiplomaticMessage(message):  # pylint: disable=invalid-name
    """Called when this player receives a diplomatic message update from the server,
    such as if another player declares war, accepts peace, or cancels a proposed peace treaty."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Ignoring diplomatic message"
        return
        
    diplomatic_corp.handle_diplomatic_message(message)
Example #57
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (
                fleet_id in universe.destroyedObjectIDs(fo.empireID())
        ):  # fleet was probably merged into another or was destroyed
            foAI.foAIstate.delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission, then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        # if (not self.hasAnyAIMissionTypes()):
        if not self.target and (system_id
                                not in set(AIstate.colonyTargetedSystemIDs +
                                           AIstate.outpostTargetedSystemIDs +
                                           AIstate.invasionTargetedSystemIDs +
                                           AIstate.blockadeTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(
                    self.fleet, start_sys_id)
                if repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            if fleet.fuel < fleet.maxFuel and self.get_location_target(
            ).id not in fleet_supplyable_system_ids:
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(
                    self.fleet, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        if self.target:
            system_targets_required_to_visit = [self.target.get_system()]
            orders_to_visit_systems = MoveUtilsAI.get_fleet_orders_from_system_targets(
                self.fleet, system_targets_required_to_visit)
            # TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
            for fleet_order in orders_to_visit_systems:
                self.orders.append(fleet_order)

        # if fleet is in some system = fleet.system_id >=0, then also generate system AIFleetOrders
        if system_id >= 0 and self.target:
            # system in where fleet is
            system_target = System(system_id)
            # if mission aiTarget has required system where fleet is, then generate fleet_order from this aiTarget
            # for all targets in all mission types get required systems to visit
            if system_target == self.target.get_system():
                # from target required to visit get fleet orders to accomplish target
                fleet_order = self._get_fleet_order_from_target(
                    self.type, self.target)
                self.orders.append(fleet_order)
Example #58
0
def _system_to_supply_group() -> Mapping[SystemId, int]:
    """
    Create a mapping of SystemIds to supply_group_id.
    Used buy supply_connected, get_supply_group_id and get_supply_group.
    """
    result = {}
    for num, group in enumerate(fo.getEmpire().resourceSupplyGroups, start=1):
        result.update((sys_id, num) for sys_id in group)
    return result
Example #59
0
def update_explored_systems():
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    obs_lanes = empire.obstructedStarlanes()
    #print "object is: %s"%(obs_lanes, ) #IntPairVec
    obs_lanes_list = [el for el in obs_lanes
                      ]  # should result in list of tuples (sys_id1, sys_id2)
    if obs_lanes_list:
        print "obstructed starlanes are: %s" % obs_lanes_list
    else:
        print "No obstructed Starlanes"
    empire_id = foAI.foAIstate.empireID
    newly_explored = []
    still_unexplored = []
    for sys_id in list(foAI.foAIstate.unexploredSystemIDs):
        if empire.hasExploredSystem(
                sys_id
        ):  # consider making determination according to visibility rather than actual visit, which I think is what empire.hasExploredSystem covers
            del foAI.foAIstate.unexploredSystemIDs[sys_id]
            foAI.foAIstate.exploredSystemIDs[sys_id] = 1
            sys = universe.getSystem(sys_id)
            print "Moved system %d ( %s ) from unexplored list to explored list" % (
                sys_id, (sys and sys.name) or "name unknown")
            if sys_id in borderUnexploredSystemIDs:
                del borderUnexploredSystemIDs[sys_id]
            newly_explored.append(sys_id)
        else:
            still_unexplored.append(sys_id)

    neighbor_list = []
    dummy = []
    for id_list, next_list in [(newly_explored, neighbor_list),
                               (neighbor_list, dummy)]:
        for sys_id in id_list:
            neighbors = list(universe.getImmediateNeighbors(sys_id, empire_id))
            all_explored = True
            for neighbor_id in neighbors:
                if neighbor_id in foAI.foAIstate.unexploredSystemIDs:  # when it matters, unexplored will be smaller than explored
                    all_explored = False
                else:
                    next_list.append(neighbor_id)
            if all_explored:
                interiorExploredSystemIDs[sys_id] = 1
                if sys_id in borderExploredSystemIDs:
                    del borderExploredSystemIDs[sys_id]
            else:
                borderExploredSystemIDs[sys_id] = 1

    for sys_id in still_unexplored:
        neighbors = list(universe.getImmediateNeighbors(sys_id, empire_id))
        any_explored = False
        for neighbor_id in neighbors:
            if neighbor_id in foAI.foAIstate.exploredSystemIDs:  # consider changing to unexplored test -- when it matters, unexplored will be smaller than explored, but need to not get previously untreated neighbors
                any_explored = True
        if any_explored:
            borderUnexploredSystemIDs[sys_id] = 1
    return newly_explored
Example #60
0
def _calculate_colonisation_priority():
    """Calculates the demand for colony ships by colonisable planets."""
    global allottedColonyTargets
    enemies_sighted = foAI.foAIstate.misc.get('enemies_sighted', {})
    galaxy_is_sparse = ColonisationAI.galaxy_is_sparse()
    total_pp = fo.getEmpire().productionPoints
    num_colonies = state.get_number_of_colonies()
    colony_growth_barrier = foAI.foAIstate.character.max_number_colonies()
    if num_colonies > colony_growth_barrier:
        return 0.0
    colony_cost = AIDependencies.COLONY_POD_COST * (1 + AIDependencies.COLONY_POD_UPKEEP * num_colonies)
    turns_to_build = 8  # TODO: check for susp anim pods, build time 10
    mil_prio = foAI.foAIstate.get_priority(PriorityType.PRODUCTION_MILITARY)
    allotted_portion = ([[[0.6, 0.8], [0.3, 0.4]], [[0.8, 0.9], [0.4, 0.6]]][galaxy_is_sparse]
                        [any(enemies_sighted)])
    allotted_portion = foAI.foAIstate.character.preferred_colonization_portion(allotted_portion)
    # if ( foAI.foAIstate.get_priority(AIPriorityType.PRIORITY_PRODUCTION_COLONISATION)
    # > 2 * foAI.foAIstate.get_priority(AIPriorityType.PRIORITY_PRODUCTION_MILITARY)):
    # allotted_portion *= 1.5
    if mil_prio < 100:
        allotted_portion *= 2
    elif mil_prio < 200:
        allotted_portion *= 1.5
    elif fo.currentTurn() > 100:
        allotted_portion *= 0.75 ** (num_colonies / 10.0)
    # allottedColonyTargets = 1+ int(fo.currentTurn()/50)
    allottedColonyTargets = 1 + int(total_pp * turns_to_build * allotted_portion / colony_cost)
    outpost_prio = foAI.foAIstate.get_priority(PriorityType.PRODUCTION_OUTPOST)

    # if have no SP_SLY, and have any outposts to build, don't build colony ships TODO: make more complex assessment
    colonizers = list(ColonisationAI.empire_colonizers)
    if "SP_SLY" not in colonizers and outpost_prio > 0:
        return 0.0
    colony_opportunities = [species_name for (_, (score, species_name)) in foAI.foAIstate.colonisablePlanetIDs.items()
                            if score > 60]
    num_colonisable_planet_ids = len(colony_opportunities)
    if num_colonisable_planet_ids == 0:
        return 1

    colony_ship_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.COLONISATION)
    num_colony_ships = len(FleetUtilsAI.extract_fleet_ids_without_mission_types(colony_ship_ids))
    colonisation_priority = 60 * (1.0 + num_colonisable_planet_ids - num_colony_ships) / (num_colonisable_planet_ids + 1)

    if colonizers == ["SP_SLY"]:
        colonisation_priority *= 2
    elif "SP_SLY" in colonizers:
        colonisation_priority *= (1.0 + colony_opportunities.count("SP_SLY")) / num_colonisable_planet_ids

    # print
    # print "Number of Colony Ships : " + str(num_colony_ships)
    # print "Number of Colonisable planets : " + str(num_colonisable_planet_ids)
    # print "Priority for colony ships : " + str(colonisation_priority)

    if colonisation_priority < 1:
        return 0
    return colonisation_priority