Example #1
0
def system_could_have_unknown_stationary_guard(system_id: SystemId) -> bool:
    """Return True if the system may have spawned stationary guards.

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

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

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

    # No indicator that there isn't a stationary guard
    return True
Example #2
0
def galaxy_is_sparse():
    setup_data = fo.getGalaxySetupData()
    avg_empire_systems = setup_data.size // len(fo.allEmpireIDs())
    return (setup_data.monsterFrequency <=
            fo.galaxySetupOptionMonsterFreq.veryLow) and (
                (avg_empire_systems >= 40) or
                ((avg_empire_systems >= 35) and
                 (setup_data.shape != fo.galaxyShape.elliptical)))
def inspect_ai_interface():
    capital_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    fleets_int_vector = universe.fleetIDs
    fleet = universe.getFleet(list(fleets_int_vector)[0])
    ship = universe.getShip(list(universe.shipIDs)[0])
    design = fo.getShipDesign(ship.designID)
    empire = fo.getEmpire()

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

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

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

    research_queue = empire.researchQueue

    fo.issueEnqueueTechOrder('SHP_WEAPON_1_2', -1)

    planet = universe.getPlanet(capital_id)

    building = list(planet.buildingIDs)[0]

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

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

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

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

    research_queue = empire.researchQueue

    fo.issueEnqueueTechOrder('SHP_WEAPON_1_2', -1)

    planet = universe.getPlanet(capital_id)

    building = list(planet.buildingIDs)[0]

    inspect(
        fo,
        universe,
        fleet,
        planet,
        universe.getSystem(planet.systemID),
        ship,
        empire,
        design,
        tech,
        tech_spec,
        fo.getFieldType('FLD_ION_STORM'),
        fo.getBuildingType('BLD_SHIPYARD_BASE'),
        fo.getGalaxySetupData(),
        fo.getHullType('SH_XENTRONIUM'),
        fo.getPartType('SR_WEAPON_1_1'),
        fo.getSpecial('MODERATE_TECH_NATIVES_SPECIAL'),
        fo.getSpecies('SP_ABADDONI'),
        fo.getTech('SHP_WEAPON_4_1'),
        fo.diplomaticMessage(1, 2, fo.diplomaticMessageType.acceptProposal),
        fleets_int_vector,
        part_type,
        prod_queue,
        prod_queue.allocatedPP,
        prod_queue[0],
        research_queue,
        research_queue[0],
        empire.getSitRep(0),
        universe.getBuilding(building),
    )
    exit(1)  # exit game to main menu no need to play anymore.
Example #5
0
 def init(self):
     rng = random.Random()
     rng.seed(fo.getEmpire().name + fo.getGalaxySetupData().seed)
     self.engine = rng.random() < 0.7
     self.fuel = rng.random() < 0.7
     self.hull = rng.randrange(4)
     self.extra_organic_hull = rng.random() < 0.05
     self.extra_robotic_hull = rng.random() < 0.05
     self.extra_asteroid_hull = rng.random() < 0.05
     self.extra_energy_hull = rng.random() < 0.05
Example #6
0
def set_game_turn_seed():
    """
    Set the random seed for game-reload consistency.

    Seed is based on galaxy seed, empire name and current turn.
    """
    turn = fo.currentTurn()
    random_seed = str(
        fo.getGalaxySetupData().seed) + "%05d%s" % (turn, fo.getEmpire().name)
    random.seed(random_seed)
Example #7
0
def _choose_aggression():
    galaxy_setup_data = fo.getGalaxySetupData()
    aggression = int(galaxy_setup_data.maxAIAggression)

    if aggression > 0:
        rng = random.Random()
        galaxy_seed = hash(galaxy_setup_data.seed)
        empire_seed = 3 * hash(fo.getEmpire().name)
        rng.seed(galaxy_seed * empire_seed)

        random_number = rng.randint(0, 99)
        if random_number > 74:
            aggression -= 1

    return fo.aggression(aggression)
Example #8
0
def generateOrders():  # pylint: disable=invalid-name
    """Called once per turn to tell the Python AI to generate and issue orders to control its empire.
    at end of this function, fo.doneTurn() should be called to indicate to the client that orders are finished
    and can be sent to the server for processing."""

    rules = fo.getGameRules()
    print "Defined game rules:"
    for rule in rules.getRulesAsStrings:
        print "Name: " + rule.name + "  value: " + str(rule.value)
    print "Rule RULE_NUM_COMBAT_ROUNDS value: " + str(
        rules.getInt("RULE_NUM_COMBAT_ROUNDS"))

    empire = fo.getEmpire()
    if empire is None:
        print "This client has no empire. Doing nothing to generate orders."
        try:
            # early abort if no empire. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            #
            # note that doneTurn() is issued on behalf of the client network
            # id, not the empire id, so not having a correct empire id does
            # not invalidate doneTurn()
            fo.doneTurn()
        except Exception as e:
            print_error(e)
        return

    if empire.eliminated:
        print "This empire has been eliminated. Aborting order generation"
        try:
            # early abort if already eliminated. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            fo.doneTurn()
        except Exception as e:
            print_error(e)
        return

    # This code block is required for correct AI work.
    print "Meter / Resource Pool updating..."
    fo.initMeterEstimatesDiscrepancies()
    fo.updateMeterEstimates(False)
    fo.updateResourcePools()

    turn = fo.currentTurn()
    turn_uid = foAIstate.set_turn_uid()
    print "\n\n\n", "=" * 20,
    print "Starting turn %s (%s) of game: %s" % (turn, turn_uid,
                                                 foAIstate.uid),
    print "=" * 20, "\n"

    turn_timer.start("AI planning")
    # set the random seed (based on galaxy seed, empire name and current turn)
    # for game-reload consistency.
    random_seed = str(
        fo.getGalaxySetupData().seed) + "%05d%s" % (turn, fo.getEmpire().name)
    random.seed(random_seed)

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    planet_id = PlanetUtilsAI.get_capital()
    planet = None
    if planet_id is not None:
        planet = universe.getPlanet(planet_id)
    aggression_name = get_trait_name_aggression(foAIstate.character)
    print "***************************************************************************"
    print "*******  Log info for AI progress chart script. Do not modify.   **********"
    print("Generating Orders")
    print(
        "EmpireID: {empire.empireID}"
        " Name: {empire.name}_{empire.empireID}_pid:{p_id}_{p_name}RIdx_{res_idx}_{aggression}"
        " Turn: {turn}").format(empire=empire,
                                p_id=fo.playerID(),
                                p_name=fo.playerName(),
                                res_idx=ResearchAI.get_research_index(),
                                turn=turn,
                                aggression=aggression_name.capitalize())
    print "EmpireColors: {0.colour.r} {0.colour.g} {0.colour.b} {0.colour.a}".format(
        empire)
    if planet:
        print "CapitalID: " + str(
            planet_id
        ) + " Name: " + planet.name + " Species: " + planet.speciesName
    else:
        print "CapitalID: None Currently Name: None Species: None "
    print "***************************************************************************"
    print "***************************************************************************"

    if turn == 1:
        declare_war_on_all()
        human_player = fo.empirePlayerID(1)
        greet = diplomatic_corp.get_first_turn_greet_message()
        fo.sendChatMessage(
            human_player, '%s (%s): [[%s]]' %
            (empire.name, get_trait_name_aggression(
                foAIstate.character), greet))

    # turn cleanup !!! this was formerly done at start of every turn -- not sure why
    foAIstate.split_new_fleets()

    foAIstate.refresh(
    )  # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
    foAIstate.report_system_threats()
    print("Calling AI Modules")
    # call AI modules
    action_list = [
        ColonisationAI.survey_universe,
        ProductionAI.find_best_designs_this_turn,
        PriorityAI.calculate_priorities,
        ExplorationAI.assign_scouts_to_explore_systems,
        ColonisationAI.assign_colony_fleets_to_colonise,
        InvasionAI.assign_invasion_fleets_to_invade,
        MilitaryAI.assign_military_fleets_to_systems,
        FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
        FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
        ResearchAI.generate_research_orders,
        ProductionAI.generate_production_orders,
        ResourcesAI.generate_resources_orders,
    ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            print_error(e, location=action.__name__)
    main_timer.stop_print_and_clear()
    turn_timer.stop_print_and_clear()
    turn_timer.start("Server_Processing")

    try:
        fo.doneTurn()
    except Exception as e:
        print_error(e)  # TODO move it to cycle above

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass
Example #9
0
def generateOrders():  # pylint: disable=invalid-name
    """Called once per turn to tell the Python AI to generate and issue orders to control its empire.
    at end of this function, fo.doneTurn() should be called to indicate to the client that orders are finished
    and can be sent to the server for processing."""
    turn_timer.start("AI planning")
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    planet_id = PlanetUtilsAI.get_capital()
    # set the random seed (based on galaxy seed, empire ID and current turn)
    # for game-reload consistency
    random_seed = str(fo.getGalaxySetupData().seed) + "%03d%05d" % (
        fo.empireID(), fo.currentTurn())
    random.seed(random_seed)
    planet = None
    if planet_id is not None:
        planet = universe.getPlanet(planet_id)
    aggression_name = fo.aggression.values[foAIstate.aggression].name
    print "***************************************************************************"
    print "**********   String for chart. Do not modify.   ***************************"
    print("Generating Orders")
    print(
        "EmpireID: {empire.empireID}"
        " Name: {empire.name}_{empire.empireID}_pid:{p_id}_{p_name}RIdx_{res_idx}_{aggression}"
        " Turn: {turn}").format(empire=empire,
                                p_id=fo.playerID(),
                                p_name=fo.playerName(),
                                res_idx=ResearchAI.get_research_index(),
                                turn=fo.currentTurn(),
                                aggression=aggression_name.capitalize())
    print "EmpireColors: {0.colour.r} {0.colour.g} {0.colour.b} {0.colour.a}".format(
        empire)
    if planet:
        print "CapitalID: " + str(
            planet_id
        ) + " Name: " + planet.name + " Species: " + planet.speciesName
    else:
        print "CapitalID: None Currently Name: None Species: None "
    print "***************************************************************************"
    print "***************************************************************************"

    if fo.currentTurn() == 1:
        declare_war_on_all()
        human_player = fo.empirePlayerID(1)
        fo.sendChatMessage(
            human_player,
            '%s Empire (%s):\n"Ave, Human, morituri te salutant!"' %
            (empire.name, aggression_name))

    # turn cleanup !!! this was formerly done at start of every turn -- not sure why
    foAIstate.split_new_fleets()

    foAIstate.refresh(
    )  # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
    foAIstate.report_system_threats()
    # ...missions
    # ...demands/priorities
    print("Calling AI Modules")
    # call AI modules
    action_list = [
        PriorityAI.calculate_priorities,
        ExplorationAI.assign_scouts_to_explore_systems,
        ColonisationAI.assign_colony_fleets_to_colonise,
        InvasionAI.assign_invasion_fleets_to_invade,
        MilitaryAI.assign_military_fleets_to_systems,
        FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
        FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
        ResearchAI.generate_research_orders,
        ProductionAI.generateProductionOrders,
        ResourcesAI.generate_resources_orders,
        foAIstate.after_turn_cleanup,
    ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            print_error(e, location=action.__name__)
    main_timer.end()
    turn_timer.end()
    turn_timer.start("Server_Processing")

    try:
        fo.doneTurn()
    except Exception as e:
        print_error(e)  # TODO move it to cycle above

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass
Example #10
0
def generateOrders():  # pylint: disable=invalid-name
    """
    Called once per turn to tell the Python AI to generate
    and issue orders, i.e. to control its empire.

    After leaving this function, the AI's turn will be finished
    and its orders will be sent to the server.
    """
    try:
        rules = fo.getGameRules()
        debug("Defined game rules:")
        for rule_name, rule_value in rules.getRulesAsStrings().items():
            debug("%s: %s", rule_name, rule_value)
        debug("Rule RULE_NUM_COMBAT_ROUNDS value: " +
              str(rules.getInt("RULE_NUM_COMBAT_ROUNDS")))
    except Exception as e:
        error("Exception %s when trying to get game rules" % e, exc_info=True)

    # If nothing can be ordered anyway, exit early.
    # Note that there is no need to update meters etc. in this case.
    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Aborting order generation.")
        return

    if empire.eliminated:
        info("This empire has been eliminated. Aborting order generation.")
        return

    # This code block is required for correct AI work.
    info("Meter / Resource Pool updating...")
    fo.initMeterEstimatesDiscrepancies()
    fo.updateMeterEstimates(False)
    fo.updateResourcePools()

    turn = fo.currentTurn()
    aistate = get_aistate()
    debug("\n\n\n" + "=" * 20)
    debug(f"Starting turn {turn}")
    debug("=" * 20 + "\n")

    turn_timer.start("AI planning")
    # set the random seed (based on galaxy seed, empire name and current turn)
    # for game-reload consistency.
    random_seed = str(
        fo.getGalaxySetupData().seed) + "%05d%s" % (turn, fo.getEmpire().name)
    random.seed(random_seed)
    empire = fo.getEmpire()
    aggression_name = get_trait_name_aggression(aistate.character)
    debug(
        "***************************************************************************"
    )
    debug(
        "*******  Log info for AI progress chart script. Do not modify.   **********"
    )
    debug("Generating Orders")

    name_parts = (
        empire.name,
        empire.empireID,
        "pid",
        fo.playerID(),
        fo.playerName(),
        "RIdx",
        ResearchAI.get_research_index(),
        aggression_name.capitalize(),
    )
    empire_name = "_".join(str(part) for part in name_parts)

    debug(f"EmpireID: {empire.empireID} Name: {empire_name} Turn: {turn}")

    debug(f"EmpireColors: {empire.colour}")
    planet_id = PlanetUtilsAI.get_capital()
    if planet_id:
        planet = fo.getUniverse().getPlanet(planet_id)
        debug("CapitalID: " + str(planet_id) + " Name: " + planet.name +
              " Species: " + planet.speciesName)
    else:
        debug("CapitalID: None Currently Name: None Species: None ")
    debug(
        "***************************************************************************"
    )
    debug(
        "***************************************************************************"
    )

    # When loading a savegame, the AI will already have issued orders for this turn.
    # To avoid duplicate orders, generally try not to replay turns. However, for debugging
    # purposes it is often useful to replay the turn and observe varying results after
    # code changes. Set the replay_after_load flag in the AI config to let the AI issue
    # new orders after a game load. Note that the orders from the original savegame are
    # still being issued and the AIstate was saved after those orders were issued.
    # TODO: Consider adding an option to clear AI orders after load (must save AIstate at turn start then)
    if fo.currentTurn() == aistate.last_turn_played:
        info("The AIstate indicates that this turn was already played.")
        if not check_bool(get_option_dict().get("replay_turn_after_load",
                                                "False")):
            info(
                "Aborting new order generation. Orders from savegame will still be issued."
            )
            return
        info("Issuing new orders anyway.")

    if turn == 1:
        human_player = fo.empirePlayerID(1)
        greet = diplomatic_corp.get_first_turn_greet_message()
        fo.sendChatMessage(
            human_player, "%s (%s): [[%s]]" %
            (empire.name, get_trait_name_aggression(aistate.character), greet))

    aistate.prepare_for_new_turn()
    debug("Calling AI Modules")
    # call AI modules
    action_list = [
        ColonisationAI.survey_universe,
        ShipDesignAI.Cache.update_for_new_turn,
        PriorityAI.calculate_priorities,
        ExplorationAI.assign_scouts_to_explore_systems,
        ColonisationAI.assign_colony_fleets_to_colonise,
        InvasionAI.assign_invasion_fleets_to_invade,
        MilitaryAI.assign_military_fleets_to_systems,
        FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
        FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
        ResearchAI.generate_research_orders,
        ProductionAI.generate_production_orders,
        ResourcesAI.generate_resources_orders,
    ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            error("Exception %s while trying to %s" % (e, action.__name__),
                  exc_info=True)
    main_timer.stop_print_and_clear()
    turn_timer.stop_print_and_clear()

    turn_timer.start("Server_Processing")

    aistate.last_turn_played = fo.currentTurn()
Example #11
0
def generateOrders():  # pylint: disable=invalid-name
    """Called once per turn to tell the Python AI to generate and issue orders to control its empire.
    at end of this function, fo.doneTurn() should be called to indicate to the client that orders are finished
    and can be sent to the server for processing."""
    turn = fo.currentTurn()
    turn_uid = foAIstate.set_turn_uid()
    print "Start turn %s (%s) of game: %s" % (turn, turn_uid, foAIstate.uid)

    turn_timer.start("AI planning")
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    planet_id = PlanetUtilsAI.get_capital()
    # set the random seed (based on galaxy seed, empire ID and current turn)
    # for game-reload consistency 
    random_seed = str(fo.getGalaxySetupData().seed) + "%03d%05d" % (fo.empireID(), turn)
    random.seed(random_seed)
    planet = None
    if planet_id is not None:
        planet = universe.getPlanet(planet_id)
    aggression_name = fo.aggression.values[foAIstate.aggression].name
    print "***************************************************************************"
    print "**********   String for chart. Do not modify.   ***************************"
    print ("Generating Orders")
    print ("EmpireID: {empire.empireID}"
           " Name: {empire.name}_{empire.empireID}_pid:{p_id}_{p_name}RIdx_{res_idx}_{aggression}"
           " Turn: {turn}").format(empire=empire,  p_id=fo.playerID(), p_name=fo.playerName(),
                                   res_idx=ResearchAI.get_research_index(), turn=turn,
                                   aggression=aggression_name.capitalize())
    print "EmpireColors: {0.colour.r} {0.colour.g} {0.colour.b} {0.colour.a}".format(empire)
    if planet:
        print "CapitalID: " + str(planet_id) + " Name: " + planet.name + " Species: " + planet.speciesName
    else:
        print "CapitalID: None Currently Name: None Species: None "
    print "***************************************************************************"
    print "***************************************************************************"

    if turn == 1:
        declare_war_on_all()
        human_player = fo.empirePlayerID(1)
        fo.sendChatMessage(human_player,  '%s Empire (%s):\n"Ave, Human, morituri te salutant!"' % (empire.name, aggression_name))

    # turn cleanup !!! this was formerly done at start of every turn -- not sure why
    foAIstate.split_new_fleets()

    foAIstate.refresh()  # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
    foAIstate.report_system_threats()
    # ...missions
    # ...demands/priorities
    print("Calling AI Modules")
    # call AI modules
    action_list = [ColonisationAI.survey_universe,
                   ProductionAI.find_best_designs_this_turn,
                   PriorityAI.calculate_priorities,
                   ExplorationAI.assign_scouts_to_explore_systems,
                   ColonisationAI.assign_colony_fleets_to_colonise,
                   InvasionAI.assign_invasion_fleets_to_invade,
                   MilitaryAI.assign_military_fleets_to_systems,
                   FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
                   FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
                   ResearchAI.generate_research_orders,
                   ProductionAI.generateProductionOrders,
                   ResourcesAI.generate_resources_orders,
                   foAIstate.after_turn_cleanup,
                   ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            print_error(e, location=action.__name__)
    main_timer.end()
    turn_timer.end()
    turn_timer.start("Server_Processing")

    try:
        fo.doneTurn()
    except Exception as e:
        print_error(e)  # TODO move it to cycle above

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass
Example #12
0
def generateOrders():  # pylint: disable=invalid-name
    """Called once per turn to tell the Python AI to generate and issue orders to control its empire.
    at end of this function, fo.doneTurn() should be called to indicate to the client that orders are finished
    and can be sent to the server for processing."""
    empire = fo.getEmpire()
    if empire is None:
        print "This client has no empire. Doing nothing to generate orders."
        try:
            # early abort if no empire. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            #
            # note that doneTurn() is issued on behalf of the client network
            # id, not the empire id, so not having a correct empire id does
            # not invalidate doneTurn()            
            fo.doneTurn()
        except Exception as e:
            print_error(e)
        return
    
    if empire.eliminated:
        print "This empire has been eliminated. Aborting order generation"
        try:
            # early abort if already eliminated. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            fo.doneTurn()
        except Exception as e:
            print_error(e)
        return

    # This code block is required for correct AI work.
    print "Meter / Resource Pool updating..."
    fo.initMeterEstimatesDiscrepancies()
    fo.updateMeterEstimates(False)
    fo.updateResourcePools()

    turn = fo.currentTurn()
    turn_uid = foAIstate.set_turn_uid()
    print "\n\n\n", "=" * 20,
    print "Starting turn %s (%s) of game: %s" % (turn, turn_uid, foAIstate.uid),
    print "=" * 20, "\n"

    turn_timer.start("AI planning")
    # set the random seed (based on galaxy seed, empire name and current turn)
    # for game-reload consistency.
    random_seed = str(fo.getGalaxySetupData().seed) + "%05d%s" % (turn, fo.getEmpire().name)
    random.seed(random_seed)

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    planet_id = PlanetUtilsAI.get_capital()
    planet = None
    if planet_id is not None:
        planet = universe.getPlanet(planet_id)
    aggression_name = get_trait_name_aggression(foAIstate.character)
    print "***************************************************************************"
    print "*******  Log info for AI progress chart script. Do not modify.   **********"
    print ("Generating Orders")
    print ("EmpireID: {empire.empireID}"
           " Name: {empire.name}_{empire.empireID}_pid:{p_id}_{p_name}RIdx_{res_idx}_{aggression}"
           " Turn: {turn}").format(empire=empire,  p_id=fo.playerID(), p_name=fo.playerName(),
                                   res_idx=ResearchAI.get_research_index(), turn=turn,
                                   aggression=aggression_name.capitalize())
    print "EmpireColors: {0.colour.r} {0.colour.g} {0.colour.b} {0.colour.a}".format(empire)
    if planet:
        print "CapitalID: " + str(planet_id) + " Name: " + planet.name + " Species: " + planet.speciesName
    else:
        print "CapitalID: None Currently Name: None Species: None "
    print "***************************************************************************"
    print "***************************************************************************"

    if turn == 1:
        declare_war_on_all()
        human_player = fo.empirePlayerID(1)
        greet = diplomatic_corp.get_first_turn_greet_message()
        fo.sendChatMessage(human_player, '%s (%s): [[%s]]' % (empire.name, get_trait_name_aggression(foAIstate.character), greet))

    # turn cleanup !!! this was formerly done at start of every turn -- not sure why
    foAIstate.split_new_fleets()

    foAIstate.refresh()  # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
    foAIstate.report_system_threats()
    print("Calling AI Modules")
    # call AI modules
    action_list = [ColonisationAI.survey_universe,
                   ProductionAI.find_best_designs_this_turn,
                   PriorityAI.calculate_priorities,
                   ExplorationAI.assign_scouts_to_explore_systems,
                   ColonisationAI.assign_colony_fleets_to_colonise,
                   InvasionAI.assign_invasion_fleets_to_invade,
                   MilitaryAI.assign_military_fleets_to_systems,
                   FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
                   FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
                   ResearchAI.generate_research_orders,
                   ProductionAI.generate_production_orders,
                   ResourcesAI.generate_resources_orders,
                   ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            print_error(e, location=action.__name__)
    main_timer.stop_print_and_clear()
    turn_timer.stop_print_and_clear()
    turn_timer.start("Server_Processing")

    try:
        fo.doneTurn()
    except Exception as e:
        print_error(e)  # TODO move it to cycle above

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass
Example #13
0
def setPlanetResourceFoci(): #+
    "set resource focus of planets "
    newFoci = {}

    print "\n============================"
    print "Collecting info to assess Planet Focus Changes\n"
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    currentTurn = fo.currentTurn()
    # set the random seed (based on galaxy seed, empire ID and current turn)
    # for game-reload consistency 
    random_seed = str(fo.getGalaxySetupData().seed) + "%03d%05d"%(fo.empireID(),  fo.currentTurn()) + "Resources"
    random.seed(random_seed)

    freq = min(3,  ( max(5,  currentTurn-80)   )/4.0)**(1.0/3)
    if  limitAssessments and ( abs(currentTurn - lastFociCheck[0] ) <1.5*freq)   and ( random.random() < 1.0/freq ) :
        timer = 6*[time()]
    else:
        lastFociCheck[0]=currentTurn
        timer= [ time() ] # getPlanets
        empirePlanetIDs = list( PlanetUtilsAI.getOwnedPlanetsByEmpire(universe.planetIDs, empireID) )
        timer.append( time() ) #filter
        timer.append( time() ) #Priority
        #TODO: take into acct splintering of resource groups
        #fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
        #fleetSupplyablePlanetIDs = PlanetUtilsAI.getPlanetsInSystemsIDs(fleetSupplyableSystemIDs)
        ppPrio = foAI.foAIstate.getPriority(AIPriorityType.PRIORITY_RESOURCE_PRODUCTION)
        rpPrio = foAI.foAIstate.getPriority(AIPriorityType.PRIORITY_RESOURCE_RESEARCH)
        priorityRatio = float(rpPrio)/(ppPrio+0.0001)
        timer.append( time() ) # shuffle
        # not supporting Growth for general planets until also adding code to make sure would actually benefit
        #shuffle(generalPlanetIDs)
        timer.append( time() ) # targets
        planets = map(universe.getPlanet,  empirePlanetIDs)
        planetMap.clear()
        planetMap.update( zip( empirePlanetIDs,  planets))
        if useGrowth:
            for metab,  metabIncPop in ColonisationAI.empireMetabolisms.items():
                for special in [aspec for aspec in AIDependencies.metabolimBoostMap.get(metab,  []) if aspec in ColonisationAI.availableGrowthSpecials]:
                    rankedPlanets=[]
                    for pid in ColonisationAI.availableGrowthSpecials[special]:
                        planet = planetMap[pid]
                        cur_focus = planet.focus
                        pop = planet.currentMeterValue(fo.meterType.population)
                        if (pop > metabIncPop - 2*planet.size) or (GFocus not in planet.availableFoci): #not enough benefit to lose local production, or can't put growth focus here
                            continue
                        for special2 in [ "COMPUTRONIUM_SPECIAL"  ]:
                            if special2 in planet.specials:
                                break
                        else: #didn't have any specials that would override interest in growth special
                            print "Considering  Growth Focus for %s (%d) with special %s; planet has pop %.1f and %s metabolism incremental pop is %.1f"%(
                                                                                                                                                          planet.name,  pid,  special,  pop,  metab,  metabIncPop)
                            if cur_focus == GFocus:
                                pop -=4 #discourage changing current focus to minimize focus-changing penalties
                            rankedPlanets.append(  (pop,  pid,  cur_focus) )
                    if rankedPlanets == []:
                        continue
                    rankedPlanets.sort()
                    print "Considering  Growth Focus choice for  special %s; possible planet pop,  id pairs are %s"%(metab,  rankedPlanets)
                    for spSize,  spPID,  cur_focus in rankedPlanets: #index 0 should be able to set focus, but just in case...
                        result = 1
                        if cur_focus != GFocus:
                            result = fo.issueChangeFocusOrder(spPID, GFocus)
                        if result == 1:
                            newFoci[spPID] = GFocus
                            if spPID in empirePlanetIDs:
                                del empirePlanetIDs[   empirePlanetIDs.index( spPID ) ]
                            print "%s focus of planet %s (%d) at Growth Focus"%( ["set",  "left" ][  cur_focus == GFocus ] ,  planetMap[spPID].name,  spPID)
                            break
                        else:
                            print "failed setting focus of planet %s (%d) at Growth Focus; focus left at %s"%(  planetMap[spPID].name,  spPID,  planetMap[spPID].focus)
        for pid in empirePlanetIDs:
            planet = planetMap[pid]
            if "COMPUTRONIUM_SPECIAL" in planet.specials:#TODO: ensure only one (extremely rarely needed)
                curFocus = planet.focus
                if RFocus not in planet.availableFoci:
                    continue
                newFoci[pid] = RFocus
                result=0
                if curFocus != RFocus:
                    result = fo.issueChangeFocusOrder(pid, RFocus)
                    if result == 1:
                        universe.updateMeterEstimates(empirePlanetIDs)
                if curFocus == RFocus  or result==1:
                    print "%s focus of planet %s (%d) (with Computronium Moon) at Research Focus"%( ["set",  "left" ][  curFocus == RFocus ] ,  planetMap[pid].name,  pid)
                    if pid in empirePlanetIDs:
                        del empirePlanetIDs[   empirePlanetIDs.index( pid ) ]
            elif  ( ([bld.buildingTypeName for bld in map( universe.getObject,  planet.buildingIDs) if bld.buildingTypeName in
                                                ["BLD_CONC_CAMP", "BLD_CONC_CAMP_REMNANT"]] != []  ) or
                             (  [  ccspec  for ccspec in planet.specials if ccspec in [ "CONC_CAMP_MASTER_SPECIAL",  "CONC_CAMP_SLAVE_SPECIAL"  ]  ]  != [] )):
                if IFocus not in planet.availableFoci:
                    continue
                curFocus = planet.focus
                newFoci[pid] = IFocus
                result=0
                if curFocus != IFocus:
                    result = fo.issueChangeFocusOrder(pid, IFocus)
                    if result == 1:
                        print ("Tried setting %s for Concentration Camp  planet %s (%d) with species %s and current focus %s, got result %d and focus %s"%
                               ( newFoci[pid],  planet.name,  pid,  planet.speciesName, curFocus,  result,  planetMap[pid].focus ))
                        universe.updateMeterEstimates(empirePlanetIDs)
                    if (result != 1) or planetMap[pid].focus != IFocus:
                        newplanet=universe.getPlanet(pid)
                        print ("Error: Failed setting %s for Concentration Camp  planet %s (%d) with species %s and current focus %s, but new planet copy shows %s"%
                               ( newFoci[pid],  planetMap[pid].name,  pid,  planetMap[pid].speciesName, planetMap[pid].focus,  newplanet.focus ))
                if curFocus == IFocus  or result==1:
                    print "%s focus of planet %s (%d) (with Concentration Camps/Remnants) at Industry Focus"%( ["set",  "left" ][  curFocus == IFocus ] ,  planetMap[pid].name,  pid)
                    if pid in empirePlanetIDs:
                        del empirePlanetIDs[   empirePlanetIDs.index( pid ) ]

        #pp, rp = getResourceTargetTotals(empirePlanetIDs,  planetMap)
        pp, rp = getResourceTargetTotals(planetMap.keys())
        print "\n-----------------------------------------"
        print "Making Planet Focus Change Determinations\n"

        ratios = []
        #for each planet, calculate RP:PP value ratio at which industry/Mining focus and research focus would have the same total value, & sort by that
        # include a bias to slightly discourage changing foci
        curTargetPP = 0.001
        curTargetRP = 0.001
        timer.append( time() ) #loop
        has_force = empire.getTechStatus("CON_FRC_ENRG_STRC") == fo.techStatus.complete
        preset_ids = set(planetMap.keys()) - set(empirePlanetIDs)
        ctPP0,  ctRP0 = 0, 0
        for pid in preset_ids:
            nPP,  nRP  = newTargets.get(pid, {}).get( planetMap[pid].focus,  [0, 0] )
            curTargetPP += nPP
            curTargetRP +=  nRP
            iPP,  iRP  = newTargets.get(pid, {}).get( IFocus,  [0, 0] )
            ctPP0 += iPP
            ctRP0 += iRP
        
        id_set = set(empirePlanetIDs)
        for adj_round in [1, 2, 3, 4]:
            maxi_ratio = ctRP0 / max ( 0.01,  ctPP0 ) #should only change between rounds 1 and 2
            for adj_round in list(id_set):
                if round == 1: #tally max Industry
                    iPP,  iRP  = newTargets.get(pid, {}).get( IFocus,  [0, 0] )
                    ctPP0 += iPP
                    ctRP0 += iRP
                    continue
                II, IR = newTargets[pid][IFocus]
                RI, RR = newTargets[pid][RFocus]
                CI, CR = currentOutput[pid][ IFocus],  currentOutput[pid][ RFocus]
                research_penalty = (currentFocus[pid] != RFocus)
                #calculate factor F at  which     II + F * IR  ==  RI + F * RR   =====>  F = ( II-RI ) / (RR-IR)
                thisFactor = ( II-RI ) / max( 0.01,  RR-IR)  # don't let denominator be zero for planets where focus doesn't change RP
                planet = planetMap[pid]
                if adj_round == 2: #take research at planets with very cheap research
                    if  (maxi_ratio < priorityRatio) and (curTargetRP < priorityRatio * ctPP0) and (thisFactor <=1.0):
                        curTargetPP += RI #
                        curTargetRP += RR
                        newFoci[pid] = RFocus
                        id_set.discard(pid)
                    continue
                if (adj_round == 3): #take research at planets where can do reasonable balance
                    if (has_force) or (foAI.foAIstate.aggression < fo.aggression.aggressive) or (curTargetRP >= priorityRatio * ctPP0):
                        continue
                    pop = planet.currentMeterValue(fo.meterType.population)
                    t_pop = planet.currentMeterValue(fo.meterType.targetPopulation)
                    #if AI is aggressive+, and this planet in range where temporary Research focus can get an additional RP at cost of 1 PP, and still need some RP, then do it
                    if (pop < t_pop - 5):
                        continue
                    if  ( CI > II + 8) or (( (RR>II) or ((RR-CR)>=1+2*research_penalty)) and ((RR-IR)>=3) and ( (CR-IR) >= 0.7*((II-CI)(1+0.1*research_penalty) ) )):
                        curTargetPP += CI -1 - research_penalty#
                        curTargetRP +=  CR+1
                        newFoci[pid] = RFocus
                        id_set.discard(pid)
                    continue
                #adj_round == 4 assume default IFocus
                curTargetPP += II  #icurTargets initially calculated by Industry focus, which will be our default focus
                curTargetRP += IR
                newFoci[pid] = IFocus
                ratios.append( (thisFactor,  pid ) )

        ratios.sort()
        printedHeader=False
        fociMap={IFocus:"Industry",  RFocus:"Research", MFocus:"Mining",  GFocus:"Growth"}
        gotAlgo = empire.getTechStatus("LRN_ALGO_ELEGANCE") == fo.techStatus.complete
        for ratio,  pid in ratios:
            do_research = False#(newFoci[pid]==RFocus)
            if (priorityRatio < ( curTargetRP/ (curTargetPP + 0.0001)))  and not do_research: #we have enough RP
                if ratio < 1.1  and foAI.foAIstate.aggression >fo.aggression.cautious :  #but wait, RP is still super cheap relative to PP, maybe will take more RP
                    if priorityRatio < 1.5* ( curTargetRP/ (curTargetPP + 0.0001)) : #yeah, really a glut of RP, stop taking RP
                        break
                else: #RP not super cheap & we have enough, stop taking it
                    break
            II, IR = newTargets[pid][IFocus]
            RI, RR = newTargets[pid][RFocus]
            #if currentFocus[pid] == MFocus:
            #    II = max( II,  newTargets[pid][MFocus][0] )
            if do_research or (gotAlgo and (
                   (ratio > 2.0 and curTargetPP < 15) or
                   (ratio > 2.5 and curTargetPP < 25  and II > 5) or
                   (ratio > 3.0 and curTargetPP < 40  and II > 5) or
                   (ratio > 4.0 and curTargetPP < 100  and II > 10)  or
                   (  (curTargetRP+RR-IR)/max(0.001,  curTargetPP - II+RI) > 2*  priorityRatio  ))):  # we already have algo elegance and more RP would be too expensive, or overkill
                if not printedHeader:
                    printedHeader=True
                    print "Rejecting further Research Focus choices  as too expensive:"
                    print "%34s|%20s|%15s |%15s|%15s |%15s |%15s"%("                      Planet  ", " current RP/PP ", " current target RP/PP ", "current Focus ","  rejectedFocus  ", " rejected target RP/PP ",  "rejected RP-PP EQF")
                    oldFocus=currentFocus[pid]
                    cPP, cRP = currentOutput[pid][IFocus],  currentOutput[pid][RFocus]
                    otPP, otRP= newTargets[pid].get(oldFocus,  (0, 0))
                    ntPP, ntRP= newTargets[pid].get(RFocus,  (0, 0))
                    print "pID (%3d)  %22s |  c:  %5.1f / %5.1f |   cT:  %5.1f / %5.1f  |  cF: %8s |  nF: %8s  | cT:  %5.1f / %5.1f |         %.2f"%(pid,  planetMap[pid].name, cRP, cPP,   otRP, otPP,  fociMap.get(oldFocus, 'unknown'),  fociMap[RFocus] , ntRP, ntPP , ratio)
                    continue  # RP is getting too expensive, but might be willing to still allocate from a planet with less PP to lose
            #if planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0: #only set to research if  pop won't die out
            newFoci[pid] = RFocus
            curTargetRP += (RR-IR)
            curTargetPP -= (II-RI)
        print "============================"
        print "Planet Focus Assignments to achieve target RP/PP ratio of %.2f from current ratio of %.2f  ( %.1f / %.1f )"%(priorityRatio,  rp/(pp+0.0001),  rp,  pp)
        print "Max Industry assignments would result in target RP/PP ratio of %.2f  ( %.1f / %.1f )"%( ctRP0/ (ctPP0 + 0.0001), ctRP0,  ctPP0 )
        print "-------------------------------------"
        print "%34s|%20s|%15s |%15s|%15s |%15s "%("                      Planet  ", " current RP/PP ", " current target RP/PP ", "current Focus ","  newFocus  ", " new target RP/PP ")
        totalChanged=0
        for id_set in empirePlanetIDs,  preset_ids:
            for pid in id_set:
                canFocus= planetMap[pid].currentMeterValue(fo.meterType.targetPopulation) >0
                oldFocus=currentFocus[pid]
                newFocus = newFoci.get(pid,  IFocus)
                cPP, cRP = currentOutput[pid][IFocus],  currentOutput[pid][RFocus]
                otPP, otRP= newTargets[pid].get(oldFocus,  (0, 0))
                ntPP, ntRP = otPP, otRP
                if newFocus != oldFocus and newFocus in planetMap[pid].availableFoci:  #planetMap[pid].focus
                    totalChanged+=1
                    if newFocus != planetMap[pid].focus:
                        result = fo.issueChangeFocusOrder(pid, newFocus)
                        if result == 1:
                            ntPP, ntRP= newTargets[pid].get(newFocus,  (0, 0))
                        else:
                            print "Trouble changing focus of planet %s (%d) to %s"%(planetMap[pid].name,  pid,  newFocus)
                print "pID (%3d)  %22s |  c:  %5.1f / %5.1f |   cT:  %5.1f / %5.1f  |  cF: %8s |  nF: %8s  | cT:  %5.1f / %5.1f "%(pid,  planetMap[pid].name, cRP, cPP,   otRP, otPP,  fociMap.get(oldFocus, 'unknown'),  fociMap[newFocus] , ntRP, ntPP )
            print "-------------------------------------"
        print "-------------------------------------\nFinal Ratio Target (turn %4d) RP/PP : %.2f  ( %.1f / %.1f )  after %d Focus changes"%( fo.currentTurn(), curTargetRP/ (curTargetPP + 0.0001), curTargetRP,  curTargetPP ,  totalChanged)

    aPP, aRP = empire.productionPoints,  empire.resourceProduction(fo.resourceType.research)
    print "Current Output (turn %4d) RP/PP : %.2f  ( %.1f / %.1f )"%(fo.currentTurn(),  aRP/ (aPP + 0.0001), aRP,  aPP ), "\n------------------------"

    timer.append( time() ) #end
    if doResourceTiming and timer_entries==__timerEntries2:
        times = [timer[i] - timer[i-1] for i in range(1,  len(timer) ) ]
        timeFmt = "%30s: %8d msec  "
        print "ResourcesAI Time Requirements:"
        for mod,  modTime in zip(timer_entries,  times):
            print timeFmt%((30*' '+mod)[-30:],  int(1000*modTime))
        if resourceTimerFile:
            print "len times: %d  ;  len entries: %d "%(len(times),  len(timer_entries))
            resourceTimerFile.write(  __timerFileFmt%tuple( [ fo.currentTurn() ]+map(lambda x: int(1000*x),  times )) +'\n')
            resourceTimerFile.flush()
Example #14
0
def generateOrders():  # pylint: disable=invalid-name
    """Called once per turn to tell the Python AI to generate and issue orders to control its empire.
    at end of this function, fo.doneTurn() should be called to indicate to the client that orders are finished
    and can be sent to the server for processing."""
    try:
        rules = fo.getGameRules()
        debug("Defined game rules:")
        for rule_name, rule_value in rules.getRulesAsStrings().items():
            debug("%s: %s", rule_name, rule_value)
        debug("Rule RULE_NUM_COMBAT_ROUNDS value: " + str(rules.getInt("RULE_NUM_COMBAT_ROUNDS")))
    except Exception as e:
        error("Exception %s when trying to get game rules" % e, exc_info=True)

    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Doing nothing to generate orders.")
        try:
            # early abort if no empire. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            #
            # note that doneTurn() is issued on behalf of the client network
            # id, not the empire id, so not having a correct empire id does
            # not invalidate doneTurn()
            fo.doneTurn()
        except Exception as e:
            error("Exception %s in doneTurn() on non-existent empire" % e, exc_info=True)
        return

    if empire.eliminated:
        debug("This empire has been eliminated. Aborting order generation")
        try:
            # early abort if already eliminated. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            fo.doneTurn()
        except Exception as e:
            error("Exception %s while trying doneTurn() on eliminated empire" % e, exc_info=True)
        return

    # This code block is required for correct AI work.
    info("Meter / Resource Pool updating...")
    fo.initMeterEstimatesDiscrepancies()
    fo.updateMeterEstimates(False)
    fo.updateResourcePools()

    turn = fo.currentTurn()
    aistate = get_aistate()
    turn_uid = aistate.set_turn_uid()
    debug("\n\n\n" + "=" * 20)
    debug("Starting turn %s (%s) of game: %s" % (turn, turn_uid, aistate.uid))
    debug("=" * 20 + "\n")

    turn_timer.start("AI planning")
    # set the random seed (based on galaxy seed, empire name and current turn)
    # for game-reload consistency.
    random_seed = str(fo.getGalaxySetupData().seed) + "%05d%s" % (turn, fo.getEmpire().name)
    random.seed(random_seed)

    universe = fo.getUniverse()
    empire = fo.getEmpire()
    planet_id = PlanetUtilsAI.get_capital()
    planet = None
    if planet_id is not None:
        planet = universe.getPlanet(planet_id)
    aggression_name = get_trait_name_aggression(aistate.character)
    debug("***************************************************************************")
    debug("*******  Log info for AI progress chart script. Do not modify.   **********")
    debug("Generating Orders")
    debug("EmpireID: {empire.empireID}"
          " Name: {empire.name}_{empire.empireID}_pid:{p_id}_{p_name}RIdx_{res_idx}_{aggression}"
          " Turn: {turn}".format(empire=empire, p_id=fo.playerID(), p_name=fo.playerName(),
                                 res_idx=ResearchAI.get_research_index(), turn=turn,
                                 aggression=aggression_name.capitalize()))
    debug("EmpireColors: {0.colour.r} {0.colour.g} {0.colour.b} {0.colour.a}".format(empire))
    if planet:
        debug("CapitalID: " + str(planet_id) + " Name: " + planet.name + " Species: " + planet.speciesName)
    else:
        debug("CapitalID: None Currently Name: None Species: None ")
    debug("***************************************************************************")
    debug("***************************************************************************")

    # When loading a savegame, the AI will already have issued orders for this turn.
    # To avoid duplicate orders, generally try not to replay turns. However, for debugging
    # purposes it is often useful to replay the turn and observe varying results after
    # code changes. Set the replay_after_load flag in the AI config to let the AI issue
    # new orders after a game load. Note that the orders from the original savegame are
    # still being issued and the AIstate was saved after those orders were issued.
    # TODO: Consider adding an option to clear AI orders after load (must save AIstate at turn start then)
    if fo.currentTurn() == aistate.last_turn_played:
        info("The AIstate indicates that this turn was already played.")
        if not check_bool(get_option_dict().get('replay_turn_after_load', 'False')):
            info("Aborting new order generation. Orders from savegame will still be issued.")
            try:
                fo.doneTurn()
            except Exception as e:
                error("Exception %s while trying doneTurn()" % e, exc_info=True)
            return
        else:
            info("Issuing new orders anyway.")

    if turn == 1:
        human_player = fo.empirePlayerID(1)
        greet = diplomatic_corp.get_first_turn_greet_message()
        fo.sendChatMessage(human_player,
                           '%s (%s): [[%s]]' % (empire.name, get_trait_name_aggression(aistate.character), greet))

    aistate.prepare_for_new_turn()
    turn_state.state.update()
    debug("Calling AI Modules")
    # call AI modules
    action_list = [ColonisationAI.survey_universe,
                   ProductionAI.find_best_designs_this_turn,
                   PriorityAI.calculate_priorities,
                   ExplorationAI.assign_scouts_to_explore_systems,
                   ColonisationAI.assign_colony_fleets_to_colonise,
                   InvasionAI.assign_invasion_fleets_to_invade,
                   MilitaryAI.assign_military_fleets_to_systems,
                   FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
                   FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
                   ResearchAI.generate_research_orders,
                   ProductionAI.generate_production_orders,
                   ResourcesAI.generate_resources_orders,
                   ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            error("Exception %s while trying to %s" % (e, action.__name__), exc_info=True)
    main_timer.stop_print_and_clear()
    turn_timer.stop_print_and_clear()

    debug('Size of issued orders: ' + str(fo.getOrders().size))

    turn_timer.start("Server_Processing")

    try:
        fo.doneTurn()
    except Exception as e:
        error("Exception %s while trying doneTurn()" % e, exc_info=True)  # TODO move it to cycle above
    finally:
        aistate.last_turn_played = fo.currentTurn()

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass
def inspect_ai_interface():
    capital_id = PlanetUtilsAI.get_capital()
    universe = fo.getUniverse()
    fleets_int_vector = universe.fleetIDs
    fleet = universe.getFleet(list(fleets_int_vector)[0])
    ship = universe.getShip(list(universe.shipIDs)[0])
    design = fo.getShipDesign(ship.designID)
    empire = fo.getEmpire()

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

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

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

    research_queue = empire.researchQueue

    fo.issueEnqueueTechOrder('SHP_WEAPON_1_2', -1)

    planet = universe.getPlanet(capital_id)

    building = list(planet.buildingIDs)[0]

    color = empire.colour

    part_meters = ship.partMeters

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

    inspect(
        fo,
        instances=[
            meter,
            part_meters,
            color,
            universe,
            fleet,
            planet,
            universe.getSystem(planet.systemID),
            ship,
            empire,
            design,
            tech,
            tech_spec,
            fo.getFieldType('FLD_ION_STORM'),
            fo.getBuildingType('BLD_SHIPYARD_BASE'),
            fo.getGalaxySetupData(),
            fo.getHullType('SH_XENTRONIUM'),
            fo.getPartType('SR_WEAPON_1_1'),
            fo.getSpecial('MODERATE_TECH_NATIVES_SPECIAL'),
            fo.getSpecies('SP_ABADDONI'),
            fo.getTech('SHP_WEAPON_4_1'),
            fo.diplomaticMessage(1, 2, fo.diplomaticMessageType.acceptPeaceProposal),
            fleets_int_vector,
            part_type,
            prod_queue,
            prod_queue.allocatedPP,
            prod_queue[0],
            research_queue,
            research_queue[0],
            empire.getSitRep(0),
            universe.getBuilding(building)
        ],
        classes_to_ignore=(
            'IntSet', 'StringSet', 'IntIntMap', 'ShipSlotVec', 'VisibilityIntMap', 'IntDblMap',
            'IntBoolMap', 'ItemSpecVec', 'PairIntInt_IntMap', 'IntSetSet', 'StringVec',
            'IntPairVec', 'IntFltMap', 'MeterTypeStringPair', 'MeterTypeMeterMap', 'universeObject',
            # this item cannot be get from generate orders
            'diplomaticStatusUpdate',
        ),
        path='AI'
    )
    exit(1)  # exit game to main menu no need to play anymore.
Example #16
0
def generateOrders():  # pylint: disable=invalid-name
    """Called once per turn to tell the Python AI to generate and issue orders to control its empire.
    at end of this function, fo.doneTurn() should be called to indicate to the client that orders are finished
    and can be sent to the server for processing."""
    empire = fo.getEmpire()
    if empire.eliminated:
        print "This empire has been eliminated. Aborting order generation"
        try:
            # early abort if already eliminated. no need to do meter calculations
            # on last-seen gamestate if nothing can be ordered anyway...
            fo.doneTurn()
        except Exception as e:
            print_error(e)
        return

    # This code block is required for correct AI work.
    print "Meter / Resource Pool updating..."
    fo.initMeterEstimatesDiscrepancies()
    fo.updateMeterEstimates(0)
    fo.updateResourcePools()

    turn = fo.currentTurn()
    turn_uid = foAIstate.set_turn_uid()
    print "Start turn %s (%s) of game: %s" % (turn, turn_uid, foAIstate.uid)

    turn_timer.start("AI planning")
    # set the random seed (based on galaxy seed, empire name and current turn)
    # for game-reload consistency.
    random_seed = str(fo.getGalaxySetupData().seed) + "%05d%s" % (turn, fo.getEmpire().name)
    random.seed(random_seed)
    aggression_name = fo.aggression.values[foAIstate.aggression].name
    if turn == 1:
        declare_war_on_all()
        human_player = fo.empirePlayerID(1)
        fo.sendChatMessage(human_player,  '%s Empire (%s):\n"Ave, Human, morituri te salutant!"' % (empire.name, aggression_name))

    # turn cleanup !!! this was formerly done at start of every turn -- not sure why
    foAIstate.split_new_fleets()

    foAIstate.refresh()  # checks exploration border & clears roles/missions of missing fleets & updates fleet locs & threats
    foAIstate.report_system_threats()
    print("Calling AI Modules")
    # call AI modules
    action_list = [ColonisationAI.survey_universe,
                   ProductionAI.find_best_designs_this_turn,
                   PriorityAI.calculate_priorities,
                   ExplorationAI.assign_scouts_to_explore_systems,
                   ColonisationAI.assign_colony_fleets_to_colonise,
                   InvasionAI.assign_invasion_fleets_to_invade,
                   MilitaryAI.assign_military_fleets_to_systems,
                   FleetUtilsAI.generate_fleet_orders_for_fleet_missions,
                   FleetUtilsAI.issue_fleet_orders_for_fleet_missions,
                   ResearchAI.generate_research_orders,
                   ProductionAI.generateProductionOrders,
                   ResourcesAI.generate_resources_orders,
                   foAIstate.after_turn_cleanup,
                   ]

    for action in action_list:
        try:
            main_timer.start(action.__name__)
            action()
            main_timer.stop()
        except Exception as e:
            print_error(e, location=action.__name__)
    main_timer.end()
    turn_timer.end()
    turn_timer.start("Server_Processing")

    try:
        fo.doneTurn()
    except Exception as e:
        print_error(e)  # TODO move it to cycle above

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass
Example #17
0
def generateOrders(): # pylint: disable=invalid-name
    "called by client to get the AI's orders for the turn"
    global _lastTurnTimestamp
    universe = fo.getUniverse()
    turnStartTime = time() #starting AI timer here, to be sure AI doesn't get blame for any  lags in server being able to provide the Universe object
    empire = fo.getEmpire()
    planetID = PlanetUtilsAI.getCapital()
    # set the random seed (based on galaxy seed, empire ID and current turn)
    # for game-reload consistency 
    random_seed = str(fo.getGalaxySetupData().seed) + "%03d%05d"%(fo.empireID(),  fo.currentTurn())
    random.seed(random_seed)
    planet = None
    if planetID is not None:
        planet = universe.getPlanet(planetID)
    print "***************************************************************************"
    print "***************************************************************************"
    print ("Generating Orders")
    res_idx = ResearchAI.get_research_index()
    print "EmpireID:    " + str(empire.empireID) + " Name: " + empire.name+ "_"+str(empire.empireID) +"_pid:"+str(fo.playerID())+"_"+fo.playerName()+"_"+("RIdx_%d"%res_idx)+"_"+_aggressions.get(foAIstate.aggression,  "?") + " Turn: " + str(fo.currentTurn())
    empireColor = empire.colour
    print "EmpireColors: %d %d %d %d"% (empireColor.r,  empireColor.g,  empireColor.b,  empireColor.a)
    if planet:
        print "CapitalID: " + str(planetID) + " Name: " + planet.name + " Species: " + planet.speciesName
    else:
        print "CapitalID: None Currently      Name: None     Species: None "
    print "***************************************************************************"
    print "***************************************************************************"

    if fo.currentTurn() == 1:
        declareWarOnAll()

    # turn cleanup !!! this was formerly done at start of every turn -- not sure why
    splitNewFleets()

    #updateShipDesigns()   #should not be needed anymore;
    #updateFleetsRoles()

    foAIstate.clean() #checks exploration border & clears roles/missions of missing fleets & updates fleet locs
    foAIstate.reportSystemThreats()
    # ...missions
    # ...demands/priorities

    print("Calling AI Modules")

    # call AI modules
    timer = [time()]
    try:
        PriorityAI.calculatePriorities()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc() # try traceback.print_exc()
    timer.append( time()  )
    try:
        ExplorationAI.assignScoutsToExploreSystems()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        ColonisationAI.assignColonyFleetsToColonise()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        InvasionAI.assignInvasionFleetsToInvade()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        MilitaryAI.assignMilitaryFleetsToSystems()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        FleetUtilsAI.generateAIFleetOrdersForAIFleetMissions()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        FleetUtilsAI.issueAIFleetOrdersForAIFleetMissions()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        ResearchAI.generateResearchOrders()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        ProductionAI.generateProductionOrders()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        ResourcesAI.generateResourcesOrders()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    try:
        foAIstate.afterTurnCleanup()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()
    timer.append( time()  )
    times = [timer[i] - timer[i-1] for i in range(1,  len(timer) ) ]
    turnEndTime = time()
    timeFmt = "%30s: %8d msec  "
    print "AI Module Time Requirements:"
    for mod,  modTime in zip(timerEntries ,  times):
        print timeFmt % ((30*' '+mod)[-30:],  int(1000*modTime))
    if _timerFile:
        _timerFile.write(  _timerFileFmt% tuple( [ fo.currentTurn() ]+map(lambda x: int(1000*x),  times )) +'\n')
        _timerFile.flush()
    if _timerBucketFile:
        _timerBucketFile.write(  _timerBucketFileFmt% tuple( [ fo.currentTurn(),  (turnStartTime-_lastTurnTimestamp)*1000, (turnEndTime-turnStartTime)*1000   ]) +'\n')
        _timerBucketFile.flush()
        _lastTurnTimestamp = time()

    try:
        fo.doneTurn()
    except:
        print "Error: exception triggered and caught:  ",  traceback.format_exc()

    if using_statprof:
        try:
            statprof.stop()
            statprof.display()
            statprof.start()
        except:
            pass