Exemplo n.º 1
0
 def handle_diplomatic_status_update(self, status_update):
     """Handle an update about the diplomatic status between players, which may
     or may not include this player."""
     debug("Received diplomatic status update to %s about empire %s and empire %s" % (
         status_update.status, status_update.empire1, status_update.empire2))
     if status_update.empire2 == fo.empireID() and status_update.status == fo.diplomaticStatus.war:
         get_aistate().log_war_declaration(status_update.empire1, status_update.empire2)
Exemplo n.º 2
0
 def wrapper():
     if get_aistate() is None:
         return func()
     else:
         cache = get_aistate().misc.setdefault('caches', {}).setdefault(func.__name__, {})
         this_turn = fo.currentTurn()
         return cache[this_turn] if this_turn in cache else cache.setdefault(this_turn, func())
Exemplo n.º 3
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
            get_aistate().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)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(self.fleet, start_sys_id)
                if repair_fleet_order and repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            cur_fighter_capacity, max_fighter_capacity = FleetUtilsAI.get_fighter_capacity_of_fleet(fleet_id)
            if (fleet.fuel < fleet.maxFuel or cur_fighter_capacity < max_fighter_capacity
                    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

        if self.target:
            # for some targets fleet has to visit systems and therefore fleet visit them

            system_to_visit = (self.target.get_system() if not self.type == MissionType.PROTECT_REGION
                               else TargetSystem(self._get_target_for_protection_mission()))
            if not system_to_visit:
                return
            orders_to_visit_systems = MoveUtilsAI.create_move_orders_to_system(self.fleet, system_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)

            # also generate appropriate final orders
            fleet_order = self._get_fleet_order_from_target(self.type, self.target)
            self.orders.append(fleet_order)
Exemplo n.º 4
0
def can_travel_to_system(fleet_id, start, target, ensure_return=False):
    """
    Return list systems to be visited.

    :param fleet_id:
    :type fleet_id: int
    :param start:
    :type start: target.TargetSystem
    :param target:
    :type target:  target.TargetSystem
    :param ensure_return:
    :type ensure_return: bool
    :return:
    :rtype: list
    """
    if start == target:
        return [TargetSystem(start.id)]

    debug("Requesting path for fleet %s from %s to %s" % (fo.getUniverse().getFleet(fleet_id), start, target))
    target_distance_from_supply = -min(state.get_system_supply(target.id), 0)

    # low-aggression AIs may not travel far from supply
    if not get_aistate().character.may_travel_beyond_supply(target_distance_from_supply):
        debug("May not move %d out of supply" % target_distance_from_supply)
        return []

    min_fuel_at_target = target_distance_from_supply if ensure_return else 0
    path_info = pathfinding.find_path_with_resupply(start.id, target.id, fleet_id,
                                                    minimum_fuel_at_target=min_fuel_at_target)
    if path_info is None:
        debug("Found no valid path.")
        return []

    debug("Found valid path: %s" % str(path_info))
    return [TargetSystem(sys_id) for sys_id in path_info.path]
Exemplo n.º 5
0
def merge_fleet_a_into_b(fleet_a_id, fleet_b_id, leave_rating=0, need_rating=0, context=""):
    universe = fo.getUniverse()
    fleet_a = universe.getFleet(fleet_a_id)
    fleet_b = universe.getFleet(fleet_b_id)
    if not fleet_a or not fleet_b:
        return 0
    system_id = fleet_a.systemID
    if fleet_b.systemID != system_id:
        return 0
    remaining_rating = CombatRatingsAI.get_fleet_rating(fleet_a_id)
    transferred_rating = 0
    for ship_id in fleet_a.shipIDs:
        this_ship = universe.getShip(ship_id)
        if not this_ship:
            continue
        this_rating = CombatRatingsAI.ShipCombatStats(ship_id).get_rating()
        remaining_rating = CombatRatingsAI.rating_needed(remaining_rating, this_rating)
        if remaining_rating < leave_rating:  # merging this would leave old fleet under minimum rating, try other ships.
            continue
        transferred = fo.issueFleetTransferOrder(ship_id, fleet_b_id)
        if transferred:
            transferred_rating = CombatRatingsAI.combine_ratings(transferred_rating, this_rating)
        else:
            print "  *** transfer of ship %4d, formerly of fleet %4d, into fleet %4d failed; %s" % (
                ship_id, fleet_a_id, fleet_b_id, (" context is %s" % context) if context else "")
        if need_rating != 0 and need_rating <= transferred_rating:
            break
    fleet_a = universe.getFleet(fleet_a_id)
    aistate = get_aistate()
    if not fleet_a or fleet_a.empty or fleet_a_id in universe.destroyedObjectIDs(fo.empireID()):
        aistate.delete_fleet_info(fleet_a_id)
    aistate.update_fleet_rating(fleet_b_id)
Exemplo n.º 6
0
def get_military_fleets_with_target_system(target_system_id):
    military_mission_types = [MissionType.MILITARY,  MissionType.SECURE]
    found_fleets = []
    for fleet_mission in get_aistate().get_fleet_missions_with_any_mission_types(military_mission_types):
        if fleet_mission.target and fleet_mission.target.id == target_system_id:
            found_fleets.append(fleet_mission.fleet.id)
    return found_fleets
Exemplo n.º 7
0
def cur_best_mil_ship_rating(include_designs=False):
    """Find the best military ship we have available in this turn and return its rating.

    :param include_designs: toggles if available designs are considered or only existing ships
    :return: float: rating of the best ship
    """
    current_turn = fo.currentTurn()
    if current_turn in _best_ship_rating_cache:
        best_rating = _best_ship_rating_cache[current_turn]
        if include_designs:
            best_design_rating = ProductionAI.cur_best_military_design_rating()
            best_rating = max(best_rating, best_design_rating)
        return best_rating
    best_rating = 0.001
    universe = fo.getUniverse()
    aistate = get_aistate()
    for fleet_id in FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.MILITARY):
        fleet = universe.getFleet(fleet_id)
        for ship_id in fleet.shipIDs:
            ship_rating = CombatRatingsAI.ShipCombatStats(ship_id).get_rating(enemy_stats=aistate.get_standard_enemy())
            best_rating = max(best_rating, ship_rating)
    _best_ship_rating_cache[current_turn] = best_rating
    if include_designs:
        best_design_rating = ProductionAI.cur_best_military_design_rating()
        best_rating = max(best_rating, best_design_rating)
    return max(best_rating, 0.001)
Exemplo n.º 8
0
def set_planet_resource_foci():
    """set resource focus of planets """

    Reporter.print_resource_ai_header()
    resource_timer.start("Priority")
    # TODO: take into acct splintering of resource groups
    aistate = get_aistate()
    production_priority = aistate.get_priority(PriorityType.RESOURCE_PRODUCTION)
    research_priority = aistate.get_priority(PriorityType.RESOURCE_RESEARCH)
    priority_ratio = float(research_priority) / (production_priority + 0.0001)

    focus_manager = PlanetFocusManager()

    reporter = Reporter(focus_manager)
    reporter.capture_section_info("Unfocusable")

    set_planet_growth_specials(focus_manager)
    set_planet_production_and_research_specials(focus_manager)
    reporter.capture_section_info("Specials")

    focus_manager.calculate_planet_infos(focus_manager.raw_planet_info.keys())

    set_planet_protection_foci(focus_manager)
    reporter.capture_section_info("Protection")

    set_planet_industry_and_research_foci(focus_manager, priority_ratio)
    reporter.capture_section_info("Typical")

    reporter.print_table(priority_ratio)

    resource_timer.stop_print_and_clear()

    Reporter.print_resource_ai_footer()
Exemplo n.º 9
0
    def _portion_of_fleet_needed_here(self):
        """Calculate the portion of the fleet needed in target system considering enemy forces."""
        # TODO check rating against planets
        if assertion_fails(self.type in COMBAT_MISSION_TYPES, msg=str(self)):
            return 0
        if assertion_fails(self.target and self.target.id != INVALID_ID, msg=str(self)):
            return 0
        system_id = self.target.id
        aistate = get_aistate()
        local_defenses = MilitaryAI.get_my_defense_rating_in_system(system_id)
        potential_threat = CombatRatingsAI.combine_ratings(
            MilitaryAI.get_system_local_threat(system_id),
            MilitaryAI.get_system_neighbor_threat(system_id)
        )
        universe = fo.getUniverse()
        system = universe.getSystem(system_id)

        # tally planetary defenses
        total_defense = total_shields = 0
        for planet_id in system.planetIDs:
            planet = universe.getPlanet(planet_id)
            total_defense += planet.currentMeterValue(fo.meterType.defense)
            total_shields += planet.currentMeterValue(fo.meterType.shield)
        planetary_ratings = total_defense * (total_shields + total_defense)
        potential_threat += planetary_ratings  # TODO: rewrite to return min rating vs planets as well

        # consider safety factor just once here rather than everywhere below
        safety_factor = aistate.character.military_safety_factor()
        potential_threat *= safety_factor

        fleet_rating = CombatRatingsAI.get_fleet_rating(self.fleet.id)
        return CombatRatingsAI.rating_needed(potential_threat, local_defenses) / float(fleet_rating)
Exemplo n.º 10
0
 def issue_order(self):
     if not super(OrderMilitary, self).issue_order():
         return False
     target_sys_id = self.target.id
     fleet = self.target.get_object()
     system_status = get_aistate().systemStatus.get(target_sys_id, {})
     total_threat = sum(system_status.get(threat, 0) for threat in ('fleetThreat', 'planetThreat', 'monsterThreat'))
     combat_trigger = system_status.get('fleetThreat', 0) or system_status.get('monsterThreat', 0)
     if not combat_trigger and system_status.get('planetThreat', 0):
         universe = fo.getUniverse()
         system = universe.getSystem(target_sys_id)
         for planet_id in system.planetIDs:
             planet = universe.getPlanet(planet_id)
             if planet.ownedBy(fo.empireID()):  # TODO: also exclude at-peace planets
                 continue
             if planet.unowned and not EspionageAI.colony_detectable_by_empire(planet_id, empire=fo.empireID()):
                 continue
             if sum([planet.currentMeterValue(meter_type) for meter_type in
                     [fo.meterType.defense, fo.meterType.shield, fo.meterType.construction]]):
                 combat_trigger = True
                 break
     if not all((
                 fleet,
                 fleet.systemID == target_sys_id,
                 system_status.get('currently_visible', False),
                 not (total_threat and combat_trigger)
     )):
         self.executed = False
     return True
Exemplo n.º 11
0
    def _need_repair(self, repair_limit=0.70):
        """Check if fleet needs to be repaired.

         If the fleet is already at a system where it can be repaired, stay there until fully repaired.
         Otherwise, repair if fleet health is below specified *repair_limit*.
         For military fleets, there is a special evaluation called, cf. *MilitaryAI.avail_mil_needing_repair()*

         :param repair_limit: percentage of health below which the fleet is sent to repair
         :type repair_limit: float
         :return: True if fleet needs repair
         :rtype: bool
        """
        # TODO: More complex evaluation if fleet needs repair (consider self-repair, distance, threat, mission...)
        fleet_id = self.fleet.id
        # if we are already at a system where we can repair, make sure we use it...
        system = self.fleet.get_system()
        # TODO starlane obstruction is not considered in the next call
        nearest_dock = MoveUtilsAI.get_best_drydock_system_id(system.id, fleet_id)
        if nearest_dock == system.id:
            repair_limit = 0.99
        # if combat fleet, use military repair check
        if get_aistate().get_fleet_role(fleet_id) in COMBAT_MISSION_TYPES:
            return fleet_id in MilitaryAI.avail_mil_needing_repair([fleet_id], on_mission=bool(self.orders),
                                                                   repair_limit=repair_limit)[0]
        # TODO: Allow to split fleet to send only damaged ships to repair
        ships_cur_health, ships_max_health = FleetUtilsAI.get_current_and_max_structure(fleet_id)
        return ships_cur_health < repair_limit * ships_max_health
Exemplo n.º 12
0
def get_best_drydock_system_id(start_system_id, fleet_id):
    """

    Get system_id of best drydock capable of repair, where best is nearest drydock
    that has a current and target happiness greater than the HAPPINESS_THRESHOLD
    with a path that is not blockaded or that the fleet can fight through to with
    acceptable losses.

    :param start_system_id: current location of fleet - used to find closest target
    :type start_system_id: int
    :param fleet_id: fleet that needs path to drydock
    :type: int
    :return: most suitable system id where the fleet should be repaired.
    :rtype: int
    """
    if start_system_id == INVALID_ID:
        warn("get_best_drydock_system_id passed bad system id.")
        return None

    if fleet_id == INVALID_ID:
        warn("get_best_drydock_system_id passed bad fleet id.")
        return None

    universe = fo.getUniverse()
    start_system = TargetSystem(start_system_id)
    drydock_system_ids = set()
    for sys_id, pids in state.get_empire_drydocks().iteritems():
        if sys_id == INVALID_ID:
            warn("get_best_drydock_system_id passed bad drydock sys_id.")
            continue
        for pid in pids:
            planet = universe.getPlanet(pid)
            if (planet and
                    planet.currentMeterValue(fo.meterType.happiness) >= DRYDOCK_HAPPINESS_THRESHOLD and
                    planet.currentMeterValue(fo.meterType.targetHappiness) >= DRYDOCK_HAPPINESS_THRESHOLD):
                drydock_system_ids.add(sys_id)
                break

    sys_distances = sorted([(universe.jumpDistance(start_system_id, sys_id), sys_id)
                            for sys_id in drydock_system_ids])

    aistate = get_aistate()
    fleet_rating = aistate.get_rating(fleet_id)
    for _, dock_sys_id in sys_distances:
        dock_system = TargetSystem(dock_sys_id)
        path = can_travel_to_system(fleet_id, start_system, dock_system)

        path_rating = sum([aistate.systemStatus[path_sys.id]['totalThreat']
                           for path_sys in path])

        SAFETY_MARGIN = 10
        if SAFETY_MARGIN * path_rating <= fleet_rating:
            debug("Drydock recommendation %s from %s for fleet %s with fleet rating %.1f and path rating %.1f."
                  % (dock_system, start_system, universe.getFleet(fleet_id), fleet_rating, path_rating))
            return dock_system.id

    debug("No safe drydock recommendation from %s for fleet %s with fleet rating %.1f."
          % (start_system, universe.getFleet(fleet_id), fleet_rating))
    return None
Exemplo n.º 13
0
def try_again(mil_fleet_ids, try_reset=False, thisround=""):
    """Clear targets and orders for all specified fleets then call get_military_fleets again."""
    aistate = get_aistate()
    for fid in mil_fleet_ids:
        mission = aistate.get_fleet_mission(fid)
        mission.clear_fleet_orders()
        mission.clear_target()
    get_military_fleets(try_reset=try_reset, thisround=thisround)
Exemplo n.º 14
0
    def _calculate_threat(self):

        systems_status = get_aistate().systemStatus.get(self.sys_id, {})
        threat = self.safety_factor * CombatRatingsAI.combine_ratings(systems_status.get('fleetThreat', 0),
                                                                      systems_status.get('monsterThreat', 0) +
                                                                      + systems_status.get('planetThreat', 0))

        return self.threat_bias + threat
Exemplo n.º 15
0
def get_invasion_targeted_planet_ids(planet_ids, mission_type):
    invasion_feet_missions = get_aistate().get_fleet_missions_with_any_mission_types([mission_type])
    targeted_planets = []
    for pid in planet_ids:
        # add planets that are target of a mission
        for mission in invasion_feet_missions:
            target = TargetPlanet(pid)
            if mission.has_target(mission_type, target):
                targeted_planets.append(pid)
    return targeted_planets
Exemplo n.º 16
0
def get_empire_fleet_ids_by_role(fleet_role):
    """Returns a list with fleet_ids that have the specified role."""
    fleet_ids = get_empire_fleet_ids()
    fleet_ids_with_role = []
    aistate = get_aistate()
    for fleet_id in fleet_ids:
        if aistate.get_fleet_role(fleet_id) != fleet_role:
            continue
        fleet_ids_with_role.append(fleet_id)
    return fleet_ids_with_role
Exemplo n.º 17
0
def assign_invasion_bases():
    """Assign our troop bases to invasion targets."""
    universe = fo.getUniverse()
    all_troopbase_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.ORBITAL_INVASION)
    available_troopbase_fleet_ids = set(FleetUtilsAI.extract_fleet_ids_without_mission_types(all_troopbase_fleet_ids))

    aistate = get_aistate()
    for fid in list(available_troopbase_fleet_ids):
        if fid not in available_troopbase_fleet_ids:  # entry may have been discarded in previous loop iterations
            continue
        fleet = universe.getFleet(fid)
        if not fleet:
            continue
        sys_id = fleet.systemID
        system = universe.getSystem(sys_id)
        available_planets = set(system.planetIDs).intersection(set(aistate.qualifyingTroopBaseTargets.keys()))
        debug("Considering Base Troopers in %s, found planets %s and registered targets %s with status %s" % (
            system.name, list(system.planetIDs), available_planets,
            [(pid, aistate.qualifyingTroopBaseTargets[pid]) for pid in available_planets]))
        targets = [pid for pid in available_planets if aistate.qualifyingTroopBaseTargets[pid][1] != -1]
        if not targets:
            debug("Failure: found no valid target for troop base in system %s" % system)
            continue
        status = aistate.systemStatus.get(sys_id, {})
        local_base_troops = set(status.get('myfleets', [])).intersection(available_troopbase_fleet_ids)

        target_id = INVALID_ID
        best_score = -1
        target_troops = 0
        for pid, (p_score, p_troops) in assign_invasion_values(targets).items():
            if p_score > best_score:
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id == INVALID_ID:
            continue
        local_base_troops.discard(fid)
        found_fleets = []
        troops_needed = max(0, target_troops - FleetUtilsAI.count_troops_in_fleet(fid))
        found_stats = {}
        min_stats = {'rating': 0, 'troopCapacity': troops_needed}
        target_stats = {'rating': 10, 'troopCapacity': troops_needed + _TROOPS_SAFETY_MARGIN}

        FleetUtilsAI.get_fleets_for_mission(target_stats, min_stats, found_stats,
                                            starting_system=sys_id, fleet_pool_set=local_base_troops,
                                            fleet_list=found_fleets)
        for fid2 in found_fleets:
            FleetUtilsAI.merge_fleet_a_into_b(fid2, fid)
            available_troopbase_fleet_ids.discard(fid2)
        available_troopbase_fleet_ids.discard(fid)
        aistate.qualifyingTroopBaseTargets[target_id][1] = -1  # TODO: should probably delete
        target = TargetPlanet(target_id)
        fleet_mission = aistate.get_fleet_mission(fid)
        fleet_mission.set_target(MissionType.ORBITAL_INVASION, target)
Exemplo n.º 18
0
def build_savegame_string() -> bytes:
    """Encode the AIstate and compress the resulting string with zlib.

    To decode the string, first call zlib.decompress() on it.

    :return: compressed savegame string
    :rtype: str
    """
    from aistate_interface import get_aistate
    savegame_string = encode(get_aistate())
    return base64.b64encode(zlib.compress(savegame_string.encode('utf-8')))
Exemplo n.º 19
0
def get_invasion_targeted_planet_ids(planet_ids, mission_type):
    invasion_feet_missions = get_aistate(
    ).get_fleet_missions_with_any_mission_types([mission_type])
    targeted_planets = []
    for pid in planet_ids:
        # add planets that are target of a mission
        for mission in invasion_feet_missions:
            target = TargetPlanet(pid)
            if mission.has_target(mission_type, target):
                targeted_planets.append(pid)
    return targeted_planets
Exemplo n.º 20
0
def assess_fleet_role(fleet_id):
    """
    Assesses ShipRoles represented in a fleet and
    returns a corresponding overall fleetRole (of type MissionType).
    """
    universe = fo.getUniverse()
    ship_roles = {}
    fleet = universe.getFleet(fleet_id)
    if not fleet:
        print "couldn't get fleet with id " + str(fleet_id)
        return ShipRoleType.INVALID

    # count ship_roles
    aistate = get_aistate()
    for ship_id in fleet.shipIDs:
        ship = universe.getShip(ship_id)
        if ship.design:
            role = aistate.get_ship_role(ship.design.id)
        else:
            role = ShipRoleType.INVALID

        if role != ShipRoleType.INVALID:
            ship_roles[role] = ship_roles.get(role, 0) + 1
    # determine most common ship_role
    favourite_role = ShipRoleType.INVALID
    for ship_role in ship_roles:
        if ship_roles[ship_role] == max(ship_roles.values()):
            favourite_role = ship_role

    # assign fleet role
    if ShipRoleType.CIVILIAN_COLONISATION in ship_roles:
        selected_role = MissionType.COLONISATION
    elif ShipRoleType.BASE_COLONISATION in ship_roles:
        selected_role = MissionType.COLONISATION
    elif ShipRoleType.CIVILIAN_OUTPOST in ship_roles:
        selected_role = MissionType.OUTPOST
    elif ShipRoleType.BASE_OUTPOST in ship_roles:
        selected_role = MissionType.ORBITAL_OUTPOST
    elif ShipRoleType.BASE_INVASION in ship_roles:
        selected_role = MissionType.ORBITAL_INVASION
    elif ShipRoleType.BASE_DEFENSE in ship_roles:
        selected_role = MissionType.ORBITAL_DEFENSE
    elif ShipRoleType.MILITARY_INVASION in ship_roles:
        selected_role = MissionType.INVASION
    ####
    elif favourite_role == ShipRoleType.CIVILIAN_EXPLORATION:
        selected_role = MissionType.EXPLORATION
    elif favourite_role == ShipRoleType.MILITARY_ATTACK:
        selected_role = MissionType.MILITARY
    elif favourite_role == ShipRoleType.MILITARY:
        selected_role = MissionType.MILITARY
    else:
        selected_role = ShipRoleType.INVALID
    return selected_role
Exemplo n.º 21
0
def calculate_priorities():
    """Calculates the priorities of the AI player."""
    debug("\n{0}Preparing to Calculate Priorities{0}".format(10 * "="))
    prioritiees_timer.start('setting Production Priority')
    aistate = get_aistate()
    aistate.set_priority(PriorityType.RESOURCE_PRODUCTION,
                         50)  # let this one stay fixed & just adjust Research

    debug("\n*** Calculating Research Priority ***\n")
    prioritiees_timer.start('setting Research Priority')
    aistate.set_priority(
        PriorityType.RESOURCE_RESEARCH,
        _calculate_research_priority())  # TODO: do univ _survey before this

    debug("\n*** Updating Colonization Status ***\n")
    prioritiees_timer.start('Evaluating Colonization Status')
    ColonisationAI.get_colony_fleets(
    )  # sets aistate.colonisablePlanetIDs and many other values used by other modules

    debug("\n*** Updating Invasion Status ***\n")
    prioritiees_timer.start('Evaluating Invasion Status')
    InvasionAI.get_invasion_fleets(
    )  # sets AIstate.opponentPlanetIDs, and AIstate.invasionTargetedPlanetIDs

    debug("\n*** Updating Military Status ***\n")
    prioritiees_timer.start('Evaluating Military Status')
    MilitaryAI.get_military_fleets()

    debug("\n** Calculating Production Priorities ***\n")
    prioritiees_timer.start('reporting Production Priority')
    _calculate_industry_priority()  # purely for reporting purposes
    prioritiees_timer.start('setting Exploration Priority')

    aistate.set_priority(PriorityType.RESOURCE_TRADE, 0)
    aistate.set_priority(PriorityType.RESOURCE_CONSTRUCTION, 0)

    aistate.set_priority(PriorityType.PRODUCTION_EXPLORATION,
                         _calculate_exploration_priority())
    prioritiees_timer.start('setting Colony Priority')
    aistate.set_priority(PriorityType.PRODUCTION_COLONISATION,
                         _calculate_colonisation_priority())
    prioritiees_timer.start('setting Outpost Priority')
    aistate.set_priority(PriorityType.PRODUCTION_OUTPOST,
                         _calculate_outpost_priority())
    prioritiees_timer.start('setting Invasion Priority')
    aistate.set_priority(PriorityType.PRODUCTION_INVASION,
                         _calculate_invasion_priority())
    prioritiees_timer.start('setting Military Priority')
    aistate.set_priority(PriorityType.PRODUCTION_MILITARY,
                         _calculate_military_priority())
    prioritiees_timer.start('setting other priorities')
    aistate.set_priority(PriorityType.PRODUCTION_BUILDINGS, 25)

    prioritiees_timer.stop_print_and_clear()
Exemplo n.º 22
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    exploration_list = [start_system_id]
    aistate = get_aistate()
    while exploration_list:
        cur_system_id = exploration_list.pop()
        if cur_system_id in graph_flags:
            continue
        graph_flags.add(cur_system_id)
        system = universe.getSystem(cur_system_id)
        if cur_system_id in aistate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in aistate.visInteriorSystemIDs:
            pre_vis = "an interior system"
        else:
            pre_vis = "an unknown system"
        system_header = "*** system %s;" % system
        if fo.currentTurn() < 50:
            visibility_turn_list = sorted(universe.getVisibilityTurnsMap(
                cur_system_id, empire_id).items(),
                                          key=lambda x: x[0].numerator)
            visibility_info = ", ".join("%s: %s" % (vis.name, turn)
                                        for vis, turn in visibility_turn_list)
            debug("%s previously %s. Visibility per turn: %s " %
                  (system_header, pre_vis, visibility_info))
            status_info = []
        else:
            status_info = [system_header]

        has_been_visible = get_partial_visibility_turn(cur_system_id) > 0
        is_connected = systems_connected(cur_system_id, home_system_id)
        status_info.append("    -- is%s partially visible" %
                           ("" if has_been_visible else " not"))
        status_info.append("    -- is%s visibly connected to homesystem" %
                           ("" if is_connected else " not"))
        if has_been_visible:
            sys_status = aistate.systemStatus.setdefault(cur_system_id, {})
            aistate.visInteriorSystemIDs.add(cur_system_id)
            aistate.visBorderSystemIDs.discard(cur_system_id)
            neighbors = get_neighbors(cur_system_id)
            sys_status.setdefault("neighbors", set()).update(neighbors)
            if neighbors:
                status_info.append(" -- has neighbors %s" % sorted(neighbors))
                for sys_id in neighbors:
                    if sys_id not in aistate.exploredSystemIDs:
                        aistate.unexploredSystemIDs.add(sys_id)
                    if (sys_id not in graph_flags) and (
                            sys_id not in aistate.visInteriorSystemIDs):
                        aistate.visBorderSystemIDs.add(sys_id)
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            debug("\n".join(status_info))
            debug("----------------------------------------------------------")
Exemplo n.º 23
0
def assign_invasion_bases():
    """Assign our troop bases to invasion targets."""
    universe = fo.getUniverse()
    all_troopbase_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.ORBITAL_INVASION)
    available_troopbase_fleet_ids = set(FleetUtilsAI.extract_fleet_ids_without_mission_types(all_troopbase_fleet_ids))

    aistate = get_aistate()
    for fid in list(available_troopbase_fleet_ids):
        if fid not in available_troopbase_fleet_ids:  # entry may have been discarded in previous loop iterations
            continue
        fleet = universe.getFleet(fid)
        if not fleet:
            continue
        sys_id = fleet.systemID
        system = universe.getSystem(sys_id)
        available_planets = set(system.planetIDs).intersection(set(aistate.qualifyingTroopBaseTargets.keys()))
        debug("Considering Base Troopers in %s, found planets %s and registered targets %s with status %s" % (
            system.name, list(system.planetIDs), available_planets,
            [(pid, aistate.qualifyingTroopBaseTargets[pid]) for pid in available_planets]))
        targets = [pid for pid in available_planets if aistate.qualifyingTroopBaseTargets[pid][1] != -1]
        if not targets:
            debug("Failure: found no valid target for troop base in system %s" % system)
            continue
        status = aistate.systemStatus.get(sys_id, {})
        local_base_troops = set(status.get('myfleets', [])).intersection(available_troopbase_fleet_ids)

        target_id = INVALID_ID
        best_score = -1
        target_troops = 0
        for pid, (p_score, p_troops) in assign_invasion_values(targets).items():
            if p_score > best_score:
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id == INVALID_ID:
            continue
        local_base_troops.discard(fid)
        found_fleets = []
        troops_needed = max(0, target_troops - FleetUtilsAI.count_troops_in_fleet(fid))
        found_stats = {}
        min_stats = {'rating': 0, 'troopCapacity': troops_needed}
        target_stats = {'rating': 10, 'troopCapacity': troops_needed + _TROOPS_SAFETY_MARGIN}

        FleetUtilsAI.get_fleets_for_mission(target_stats, min_stats, found_stats,
                                            starting_system=sys_id, fleet_pool_set=local_base_troops,
                                            fleet_list=found_fleets)
        for fid2 in found_fleets:
            FleetUtilsAI.merge_fleet_a_into_b(fid2, fid)
            available_troopbase_fleet_ids.discard(fid2)
        available_troopbase_fleet_ids.discard(fid)
        aistate.qualifyingTroopBaseTargets[target_id][1] = -1  # TODO: should probably delete
        target = TargetPlanet(target_id)
        fleet_mission = aistate.get_fleet_mission(fid)
        fleet_mission.set_target(MissionType.ORBITAL_INVASION, target)
Exemplo n.º 24
0
def assess_fleet_role(fleet_id):
    """
    Assesses ShipRoles represented in a fleet and
    returns a corresponding overall fleetRole (of type MissionType).
    """
    universe = fo.getUniverse()
    ship_roles = {}
    fleet = universe.getFleet(fleet_id)
    if not fleet:
        debug("couldn't get fleet with id " + str(fleet_id))
        return ShipRoleType.INVALID

    # count ship_roles
    aistate = get_aistate()
    for ship_id in fleet.shipIDs:
        ship = universe.getShip(ship_id)
        if ship.design:
            role = aistate.get_ship_role(ship.design.id)
        else:
            role = ShipRoleType.INVALID

        if role != ShipRoleType.INVALID:
            ship_roles[role] = ship_roles.get(role, 0) + 1
    # determine most common ship_role
    favourite_role = ShipRoleType.INVALID
    for ship_role in ship_roles:
        if ship_roles[ship_role] == max(ship_roles.values()):
            favourite_role = ship_role

    # assign fleet role
    if ShipRoleType.CIVILIAN_COLONISATION in ship_roles:
        selected_role = MissionType.COLONISATION
    elif ShipRoleType.BASE_COLONISATION in ship_roles:
        selected_role = MissionType.COLONISATION
    elif ShipRoleType.CIVILIAN_OUTPOST in ship_roles:
        selected_role = MissionType.OUTPOST
    elif ShipRoleType.BASE_OUTPOST in ship_roles:
        selected_role = MissionType.ORBITAL_OUTPOST
    elif ShipRoleType.BASE_INVASION in ship_roles:
        selected_role = MissionType.ORBITAL_INVASION
    elif ShipRoleType.BASE_DEFENSE in ship_roles:
        selected_role = MissionType.ORBITAL_DEFENSE
    elif ShipRoleType.MILITARY_INVASION in ship_roles:
        selected_role = MissionType.INVASION
    ####
    elif favourite_role == ShipRoleType.CIVILIAN_EXPLORATION:
        selected_role = MissionType.EXPLORATION
    elif favourite_role == ShipRoleType.MILITARY_ATTACK:
        selected_role = MissionType.MILITARY
    elif favourite_role == ShipRoleType.MILITARY:
        selected_role = MissionType.MILITARY
    else:
        selected_role = ShipRoleType.INVALID
    return selected_role
Exemplo n.º 25
0
def fleet_has_ship_with_role(fleet_id, ship_role):
    """Returns True if a ship with shipRole is in the fleet."""
    universe = fo.getUniverse()
    fleet = universe.getFleet(fleet_id)

    if fleet is None:
        return False
    aistate = get_aistate()
    for ship_id in fleet.shipIDs:
        ship = universe.getShip(ship_id)
        if aistate.get_ship_role(ship.design.id) == ship_role:
            return True
    return False
Exemplo n.º 26
0
def fleet_has_ship_with_role(fleet_id, ship_role):
    """Returns True if a ship with shipRole is in the fleet."""
    universe = fo.getUniverse()
    fleet = universe.getFleet(fleet_id)

    if fleet is None:
        return False
    aistate = get_aistate()
    for ship_id in fleet.shipIDs:
        ship = universe.getShip(ship_id)
        if aistate.get_ship_role(ship.design.id) == ship_role:
            return True
    return False
Exemplo n.º 27
0
def _get_queued_base_troopers(sys_id: SystemId,
                              element: fo.productionQueueElement) -> float:
    """Get base troopers for given system from a build queue element"""
    aistate = get_aistate()
    if element.buildType == EmpireProductionTypes.BT_SHIP:
        planet = fo.getUniverse().getPlanet(element.locationID)
        if planet.systemID == sys_id and aistate.get_ship_role(
                element.designID) == ShipRoleType.BASE_INVASION:
            design = fo.getShipDesign(element.designID)
            troops_per_ship = design.troopCapacity * get_species_tag_value(
                planet.speciesName, Tags.ATTACKTROOPS)
            return element.remaining * element.blocksize * troops_per_ship
    return 0.0
Exemplo n.º 28
0
def assign_invasion_fleets_to_invade():
    """Assign fleet targets to invadable planets."""
    aistate = get_aistate()

    assign_invasion_bases()

    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.INVASION)
    invasion_fleet_ids = FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids)
    send_invasion_fleets(invasion_fleet_ids, AIstate.invasionTargets, MissionType.INVASION)
    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.INVASION)
    for fid in FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids):
        this_mission = aistate.get_fleet_mission(fid)
        this_mission.check_mergers(context="Post-send consolidation of unassigned troops")
Exemplo n.º 29
0
def get_empire_fleet_ids():
    """Returns all fleetIDs for current empire."""
    empire_id = fo.empireID()
    universe = fo.getUniverse()
    empire_fleet_ids = []
    destroyed_object_ids = universe.destroyedObjectIDs(empire_id)
    for fleet_id in set(list(universe.fleetIDs) + list(get_aistate().newlySplitFleets)):
        fleet = universe.getFleet(fleet_id)
        if fleet is None:
            continue
        if fleet.ownedBy(empire_id) and fleet_id not in destroyed_object_ids and not fleet.empty and fleet.shipIDs:
            empire_fleet_ids.append(fleet_id)
    return empire_fleet_ids
Exemplo n.º 30
0
def assign_invasion_fleets_to_invade():
    """Assign fleet targets to invadable planets."""
    aistate = get_aistate()

    assign_invasion_bases()

    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.INVASION)
    invasion_fleet_ids = FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids)
    send_invasion_fleets(invasion_fleet_ids, AIstate.invasionTargets, MissionType.INVASION)
    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(MissionType.INVASION)
    for fid in FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids):
        this_mission = aistate.get_fleet_mission(fid)
        this_mission.check_mergers(context="Post-send consolidation of unassigned troops")
Exemplo n.º 31
0
def get_empire_fleet_ids():
    """Returns all fleetIDs for current empire."""
    empire_id = fo.empireID()
    universe = fo.getUniverse()
    empire_fleet_ids = []
    destroyed_object_ids = universe.destroyedObjectIDs(empire_id)
    for fleet_id in set(list(universe.fleetIDs) + list(get_aistate().newlySplitFleets)):
        fleet = universe.getFleet(fleet_id)
        if fleet is None:
            continue
        if fleet.ownedBy(empire_id) and fleet_id not in destroyed_object_ids and not fleet.empty and fleet.shipIDs:
            empire_fleet_ids.append(fleet_id)
    return empire_fleet_ids
Exemplo n.º 32
0
 def __init__(self, status_only: bool = False):
     self._empire = fo.getEmpire()
     self._universe = fo.getUniverse()
     self._aistate = get_aistate()
     # resourceAvailable includes this turns production, but that is wrong for influence
     self._ip = self._empire.resourceAvailable(
         fo.resourceType.influence) - self._get_infl_prod()
     self._adopted = set(self._empire.adoptedPolicies)
     # When we continue a game in which we just adopted a policy, game state shows the policy as adopted,
     # but IP still unspent. Correct it here, then calculate anew whether we want to adopt it.
     if not status_only:
         for entry in self._empire.turnsPoliciesAdopted:
             if entry.data() == fo.currentTurn():
                 debug(f"reverting saved adopt {entry.key()}")
                 fo.issueDeadoptPolicyOrder(entry.key())
                 self._adopted.remove(entry.key())
     self._originally_adopted = copy(self._adopted)
     empire_owned_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire()
     self._populated_planet_ids = PlanetUtilsAI.get_populated_planet_ids(
         empire_owned_planet_ids)
     self._num_populated = len(self._populated_planet_ids)
     self._num_outposts = len(empire_owned_planet_ids) - self._num_populated
     self._max_turn_bureaucracy = self._calculate_max_turn_bureaucracy()
     self._centralization_cost = fo.getPolicy(centralization).adoptionCost()
     self._bureaucracy_cost = fo.getPolicy(bureaucracy).adoptionCost()
     self._wanted_ip = self._wanted_for_bureaucracy()
     self._adoptable = self._get_adoptable()
     self._available = set(self._empire.availablePolicies)
     self._rating_functions = {
         propaganda: lambda: 20 + self._rate_opinion(propaganda),
         algo_research: self._rate_algo_research,
         diversity: self._rate_diversity,
         artisans: self._rate_artisans,
         population: self._rate_population,
         # military policies are mostly chosen by opinion, plus some rule-of-thumb values
         allied_repair: lambda: self._rate_opinion(
             charge),  # no effect, unless we have allies...
         charge:
         lambda: 5 + self._rate_opinion(charge),  # A small bonus in battle
         scanning: lambda: 20 + self._rate_opinion(
             scanning),  # May help us detect ships and planets
         simplicity: lambda: 20 + self._rate_opinion(
             simplicity),  # Makes simple ships cheaper
         engineering: self._rate_engineering_corps,
         exploration: lambda: 10 + self._rate_opinion(
             exploration),  # may give a little research, speeds up scouts
         flanking: lambda: 5 + self._rate_opinion(
             flanking),  # A small bonus in battle
         recruitment: lambda: 15 + self._rate_opinion(
             recruitment),  # cheaper troop ships
     }
Exemplo n.º 33
0
def split_fleet(fleet_id):
    """Split a fleet into its ships.

    :param fleet_id: fleet to be split.
    :type fleet_id: int
    :return: New fleets. Empty if couldn't split.
    :rtype: list[int]
    """
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    fleet = universe.getFleet(fleet_id)
    newfleets = []

    if fleet is None:
        return []
    if not fleet.ownedBy(empire_id):
        return []

    if len(list(
            fleet.shipIDs)) <= 1:  # fleet with only one ship cannot be split
        return []
    ship_ids = list(fleet.shipIDs)
    aistate = get_aistate()
    for ship_id in ship_ids[1:]:
        new_fleet_id = fo.issueNewFleetOrder("Fleet %4d" % ship_id, ship_id)
        if new_fleet_id:
            new_fleet = universe.getFleet(new_fleet_id)
            if not new_fleet:
                warn("Newly split fleet %d not available from universe" %
                     new_fleet_id)
            fo.issueRenameOrder(
                new_fleet_id,
                "Fleet %4d" % new_fleet_id)  # to ease review of debugging logs
            fo.issueAggressionOrder(new_fleet_id, True)
            aistate.update_fleet_rating(new_fleet_id)
            newfleets.append(new_fleet_id)
            aistate.newlySplitFleets[new_fleet_id] = True
        else:
            if fleet.systemID == INVALID_ID:
                warn(
                    "Tried to split ship id (%d) from fleet %d when fleet is in starlane"
                    % (ship_id, fleet_id))
            else:
                warn(
                    "Got no fleet ID back after trying to split ship id (%d) from fleet %d"
                    % (ship_id, fleet_id))
    aistate.get_fleet_role(fleet_id, force_new=True)
    aistate.update_fleet_rating(fleet_id)
    if newfleets:
        aistate.ensure_have_fleet_missions(newfleets)
    return newfleets
Exemplo n.º 34
0
def avail_mil_needing_repair(mil_fleet_ids, split_ships=False, on_mission=False, repair_limit=0.70):
    """Returns tuple of lists: (ids_needing_repair, ids_not)."""
    fleet_buckets = [[], []]
    universe = fo.getUniverse()
    cutoff = [repair_limit, 0.25][on_mission]
    aistate = get_aistate()
    for fleet_id in mil_fleet_ids:
        fleet = universe.getFleet(fleet_id)
        ship_buckets = [[], []]
        ships_cur_health = [0, 0]
        ships_max_health = [0, 0]
        for ship_id in fleet.shipIDs:
            this_ship = universe.getShip(ship_id)
            cur_struc = this_ship.initialMeterValue(fo.meterType.structure)
            max_struc = this_ship.initialMeterValue(fo.meterType.maxStructure)
            ship_ok = cur_struc >= cutoff * max_struc
            ship_buckets[ship_ok].append(ship_id)
            ships_cur_health[ship_ok] += cur_struc
            ships_max_health[ship_ok] += max_struc
        this_sys_id = fleet.systemID if fleet.nextSystemID == INVALID_ID else fleet.nextSystemID
        fleet_ok = (sum(ships_cur_health) >= cutoff * sum(ships_max_health))
        local_status = aistate.systemStatus.get(this_sys_id, {})
        my_local_rating = combine_ratings(local_status.get('mydefenses', {}).get('overall', 0), local_status.get('myFleetRating', 0))
        my_local_rating_vs_planets = local_status.get('myFleetRatingVsPlanets', 0)
        combat_trigger = bool(local_status.get('fleetThreat', 0) or local_status.get('monsterThreat', 0))
        if not combat_trigger and local_status.get('planetThreat', 0):
            universe = fo.getUniverse()
            system = universe.getSystem(this_sys_id)
            for planet_id in system.planetIDs:
                planet = universe.getPlanet(planet_id)
                if planet.ownedBy(fo.empireID()):  # TODO: also exclude at-peace planets
                    continue
                if planet.unowned and not EspionageAI.colony_detectable_by_empire(planet_id, empire=fo.empireID()):
                    continue
                if sum([planet.currentMeterValue(meter_type) for meter_type in
                        [fo.meterType.defense, fo.meterType.shield, fo.meterType.construction]]):
                    combat_trigger = True
                    break
        needed_here = combat_trigger and local_status.get('totalThreat', 0) > 0  # TODO: assess if remaining other forces are sufficient
        safely_needed = needed_here and my_local_rating > local_status.get('totalThreat', 0) and my_local_rating_vs_planets > local_status.get('planetThreat', 0)  # TODO: improve both assessment prongs
        if not fleet_ok:
            if safely_needed:
                print "Fleet %d at %s needs repair but deemed safely needed to remain for defense" % (fleet_id, universe.getSystem(fleet.systemID))
            else:
                if needed_here:
                    print "Fleet %d at %s needed present for combat, but is damaged and deemed unsafe to remain." % (fleet_id, universe.getSystem(fleet.systemID))
                    print "\t my_local_rating: %.1f ; threat: %.1f" % (my_local_rating, local_status.get('totalThreat', 0))
                print "Selecting fleet %d at %s for repair" % (fleet_id, universe.getSystem(fleet.systemID))
        fleet_buckets[fleet_ok or bool(safely_needed)].append(fleet_id)
    return fleet_buckets
Exemplo n.º 35
0
def send_invasion_fleets(fleet_ids, evaluated_planets, mission_type):
    """sends a list of invasion fleets to a list of planet_value_pairs"""
    if not fleet_ids:
        return

    universe = fo.getUniverse()
    invasion_fleet_pool = set(fleet_ids)

    for planet_id, pscore, ptroops in evaluated_planets:
        if pscore < MIN_INVASION_SCORE:
            continue
        planet = universe.getPlanet(planet_id)
        if not planet:
            continue
        sys_id = planet.systemID
        found_fleets = []
        found_stats = {}
        min_stats = {"rating": 0, "troopCapacity": ptroops}
        target_stats = {
            "rating": 10,
            "troopCapacity": ptroops + _TROOPS_SAFETY_MARGIN,
            "target_system": TargetSystem(sys_id),
        }
        these_fleets = FleetUtilsAI.get_fleets_for_mission(
            target_stats,
            min_stats,
            found_stats,
            starting_system=sys_id,
            fleet_pool_set=invasion_fleet_pool,
            fleet_list=found_fleets,
        )
        if not these_fleets:
            if not FleetUtilsAI.stats_meet_reqs(found_stats, min_stats):
                debug(
                    "Insufficient invasion troop allocation for system %d ( %s ) -- requested %s , found %s"
                    % (sys_id, universe.getSystem(sys_id).name, min_stats,
                       found_stats))
                invasion_fleet_pool.update(found_fleets)
                continue
            else:
                these_fleets = found_fleets
        target = TargetPlanet(planet_id)
        debug("assigning invasion fleets %s to target %s" %
              (these_fleets, target))
        aistate = get_aistate()
        for fleetID in these_fleets:
            fleet_mission = aistate.get_fleet_mission(fleetID)
            fleet_mission.clear_fleet_orders()
            fleet_mission.clear_target()
            fleet_mission.set_target(mission_type, target)
Exemplo n.º 36
0
def _dump_empire_info():
    empire = fo.getEmpire()
    turn = fo.currentTurn()

    # TODO: It would be nice to decouple char and AI state.
    #       Character is immutable and ai state is mutable.
    #       Dependency on immutable object is easier to manage
    research_index = get_aistate().character.get_research_index()
    aggression_name = get_trait_name_aggression(get_aistate().character)

    name_parts = (
        empire.name,
        empire.empireID,
        "pid",
        fo.playerID(),
        fo.playerName(),
        "RIdx",
        research_index,
        aggression_name.capitalize(),
    )
    empire_name = "_".join(str(part) for part in name_parts)
    stats.empire(empire.empireID, empire_name, turn)
    stats.empire_color(*empire.colour)
Exemplo n.º 37
0
def avail_mil_needing_repair(mil_fleet_ids, split_ships=False, on_mission=False, repair_limit=0.70):
    """Returns tuple of lists: (ids_needing_repair, ids_not)."""
    fleet_buckets = [[], []]
    universe = fo.getUniverse()
    cutoff = [repair_limit, 0.25][on_mission]
    aistate = get_aistate()
    for fleet_id in mil_fleet_ids:
        fleet = universe.getFleet(fleet_id)
        ship_buckets = [[], []]
        ships_cur_health = [0, 0]
        ships_max_health = [0, 0]
        for ship_id in fleet.shipIDs:
            this_ship = universe.getShip(ship_id)
            cur_struc = this_ship.initialMeterValue(fo.meterType.structure)
            max_struc = this_ship.initialMeterValue(fo.meterType.maxStructure)
            ship_ok = cur_struc >= cutoff * max_struc
            ship_buckets[ship_ok].append(ship_id)
            ships_cur_health[ship_ok] += cur_struc
            ships_max_health[ship_ok] += max_struc
        this_sys_id = fleet.systemID if fleet.nextSystemID == INVALID_ID else fleet.nextSystemID
        fleet_ok = (sum(ships_cur_health) >= cutoff * sum(ships_max_health))
        local_status = aistate.systemStatus.get(this_sys_id, {})
        my_local_rating = combine_ratings(local_status.get('mydefenses', {}).get('overall', 0), local_status.get('myFleetRating', 0))
        my_local_rating_vs_planets = local_status.get('myFleetRatingVsPlanets', 0)
        combat_trigger = bool(local_status.get('fleetThreat', 0) or local_status.get('monsterThreat', 0))
        if not combat_trigger and local_status.get('planetThreat', 0):
            universe = fo.getUniverse()
            system = universe.getSystem(this_sys_id)
            for planet_id in system.planetIDs:
                planet = universe.getPlanet(planet_id)
                if planet.ownedBy(fo.empireID()):  # TODO: also exclude at-peace planets
                    continue
                if planet.unowned and not EspionageAI.colony_detectable_by_empire(planet_id, empire=fo.empireID()):
                    continue
                if sum([planet.currentMeterValue(meter_type) for meter_type in
                        [fo.meterType.defense, fo.meterType.shield, fo.meterType.construction]]):
                    combat_trigger = True
                    break
        needed_here = combat_trigger and local_status.get('totalThreat', 0) > 0  # TODO: assess if remaining other forces are sufficient
        safely_needed = needed_here and my_local_rating > local_status.get('totalThreat', 0) and my_local_rating_vs_planets > local_status.get('planetThreat', 0)  # TODO: improve both assessment prongs
        if not fleet_ok:
            if safely_needed:
                debug("Fleet %d at %s needs repair but deemed safely needed to remain for defense" % (fleet_id, universe.getSystem(fleet.systemID)))
            else:
                if needed_here:
                    debug("Fleet %d at %s needed present for combat, but is damaged and deemed unsafe to remain." % (fleet_id, universe.getSystem(fleet.systemID)))
                    debug("\t my_local_rating: %.1f ; threat: %.1f" % (my_local_rating, local_status.get('totalThreat', 0)))
                debug("Selecting fleet %d at %s for repair" % (fleet_id, universe.getSystem(fleet.systemID)))
        fleet_buckets[fleet_ok or bool(safely_needed)].append(fleet_id)
    return fleet_buckets
Exemplo n.º 38
0
    def issue_order(self):
        if not super(OrderInvade, self).can_issue_order():
            return False

        universe = fo.getUniverse()
        planet_id = self.target.id
        planet = self.target.get_object()
        fleet = self.fleet.get_object()

        invasion_roles = (ShipRoleType.MILITARY_INVASION,
                          ShipRoleType.BASE_INVASION)

        debug("Issuing order: %s fleet: %s target: %s" %
              (self.ORDER_NAME, self.fleet, self.target))
        # will track if at least one invasion troops successfully deployed
        result = False
        aistate = get_aistate()
        for ship_id in fleet.shipIDs:
            ship = universe.getShip(ship_id)
            role = aistate.get_ship_role(ship.design.id)
            if role not in invasion_roles:
                continue

            debug("Ordering troop ship %d to invade %s" % (ship_id, planet))
            result = fo.issueInvadeOrder(ship_id, planet_id) or result
            if not result:
                shields = planet.currentMeterValue(fo.meterType.shield)
                planet_stealth = planet.currentMeterValue(fo.meterType.stealth)
                pop = planet.currentMeterValue(fo.meterType.population)
                warn("Invasion order failed!")
                debug(
                    " -- planet has %.1f stealth, shields %.1f, %.1f population and "
                    "is owned by empire %d" %
                    (planet_stealth, shields, pop, planet.owner))
                if 'needsEmergencyExploration' not in dir(aistate):
                    aistate.needsEmergencyExploration = []
                if fleet.systemID not in aistate.needsEmergencyExploration:
                    aistate.needsEmergencyExploration.append(fleet.systemID)
                    debug(
                        "Due to trouble invading, adding system %d to Emergency Exploration List"
                        % fleet.systemID)
                self.executed = False
                # debug(universe.getPlanet(planet_id).dump())  # TODO: fix fo.UniverseObject.dump()
                break
        if result:
            debug("Successfully ordered troop ship(s) to invade %s" % planet)
            return True
        else:
            return False
Exemplo n.º 39
0
    def check_mergers(self, context=""):
        """
        Merge local fleets with same mission into this fleet.

        :param context: Context of the function call for logging purposes
        :type context: str
        """
        debug("Considering to merge %s", self.__str__())
        if self.type not in MERGEABLE_MISSION_TYPES:
            debug("Mission type does not allow merging.")
            return

        if not self.target:
            debug("Mission has no valid target - do not merge.")
            return

        universe = fo.getUniverse()
        empire_id = fo.empireID()

        fleet_id = self.fleet.id
        main_fleet = universe.getFleet(fleet_id)
        main_fleet_system_id = main_fleet.systemID
        if main_fleet_system_id == INVALID_ID:
            debug("Can't merge: fleet in middle of starlane.")
            return

        # only merge PROTECT_REGION if there is any threat near target
        if self.type == MissionType.PROTECT_REGION:
            neighbor_systems = universe.getImmediateNeighbors(self.target.id, empire_id)
            if not any(MilitaryAI.get_system_local_threat(sys_id)
                       for sys_id in neighbor_systems):
                debug("Not merging PROTECT_REGION fleet - no threat nearby.")
                return

        destroyed_list = set(universe.destroyedObjectIDs(empire_id))
        aistate = get_aistate()
        system_status = aistate.systemStatus[main_fleet_system_id]
        other_fleets_here = [fid for fid in system_status.get('myFleetsAccessible', []) if fid != fleet_id and
                             fid not in destroyed_list and universe.getFleet(fid).ownedBy(empire_id)]
        if not other_fleets_here:
            debug("No other fleets here")
            return

        for fid in other_fleets_here:
            fleet_mission = aistate.get_fleet_mission(fid)
            if fleet_mission.type != self.type or fleet_mission.target != self.target:
                debug("Local candidate %s does not have same mission." % fleet_mission)
                continue
            FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id, context="Order %s of mission %s" % (context, self))
Exemplo n.º 40
0
    def print_resources_priority():
        """Calculate top resource priority."""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)
        print "Resource Priorities:"
        resource_priorities = {}
        aistate = get_aistate()
        for priority_type in get_priority_resource_types():
            resource_priorities[priority_type] = aistate.get_priority(priority_type)

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

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

    debug(
        "***************************************************************************"
    )
    debug(
        "*******  Log info for AI progress chart script. Do not modify.   **********"
    )
    debug("Generating Orders")
    _dump_empire_info()
    _print_empire_capital()
    stats.ship_count(get_aistate().shipCount)
Exemplo n.º 42
0
def _pre_game_start(empire_id):
    """
    Configuration that should be done before AI start operating.
    """
    aistate = get_aistate()
    aggression_trait = aistate.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()
    configure_debug_chat(empire_id)
Exemplo n.º 43
0
def build_savegame_string(use_compression=True):
    """Encode the AIstate and compress the resulting string with zlib.

    To decode the string, first call zlib.decompress() on it.

    :return: compressed savegame string
    :rtype: str
    """
    from aistate_interface import get_aistate
    savegame_string = encode(get_aistate())
    if use_compression:
        import base64
        import zlib
        savegame_string = base64.b64encode(zlib.compress(savegame_string))
    return savegame_string
Exemplo n.º 44
0
    def can_issue_order(self, verbose=False):
        """If FleetOrder can be issued now."""
        # for some orders, may need to re-issue if invasion/outposting/colonization was interrupted
        if self.executed and not isinstance(self, (OrderOutpost, OrderColonize, OrderInvade)):
            return False
        if not self.is_valid():
            return False

        if verbose:
            sys1 = self.fleet.get_system()
            main_fleet_mission = get_aistate().get_fleet_mission(self.fleet.id)
            print "  Can issue %s - Mission Type %s (%s), current loc sys %d - %s" % (
                self, main_fleet_mission.type,
                main_fleet_mission.type, self.fleet.id, sys1)
        return True
Exemplo n.º 45
0
def build_savegame_string(use_compression=True):
    """Encode the AIstate and compress the resulting string with zlib.

    To decode the string, first call zlib.decompress() on it.

    :return: compressed savegame string
    :rtype: str
    """
    from aistate_interface import get_aistate
    savegame_string = encode(get_aistate())
    if use_compression:
        import base64
        import zlib
        savegame_string = base64.b64encode(zlib.compress(savegame_string))
    return savegame_string
Exemplo n.º 46
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    exploration_list = [start_system_id]
    aistate = get_aistate()
    while exploration_list:
        cur_system_id = exploration_list.pop()
        if cur_system_id in graph_flags:
            continue
        graph_flags.add(cur_system_id)
        system = universe.getSystem(cur_system_id)
        if cur_system_id in aistate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in aistate.visInteriorSystemIDs:
            pre_vis = "an interior system"
        else:
            pre_vis = "an unknown system"
        system_header = "*** system %s;" % system
        if fo.currentTurn() < 50:
            visibility_turn_list = sorted(universe.getVisibilityTurnsMap(cur_system_id, empire_id).items(),
                                          key=lambda x: x[0].numerator)
            visibility_info = ', '.join('%s: %s' % (vis.name, turn) for vis, turn in visibility_turn_list)
            debug("%s previously %s. Visibility per turn: %s " % (system_header, pre_vis, visibility_info))
            status_info = []
        else:
            status_info = [system_header]

        has_been_visible = get_partial_visibility_turn(cur_system_id) > 0
        is_connected = universe.systemsConnected(cur_system_id, home_system_id, -1)  # self.empire_id)
        status_info.append("    -- is%s partially visible" % ("" if has_been_visible else " not"))
        status_info.append("    -- is%s visibly connected to homesystem" % ("" if is_connected else " not"))
        if has_been_visible:
            sys_status = aistate.systemStatus.setdefault(cur_system_id, {})
            aistate.visInteriorSystemIDs.add(cur_system_id)
            aistate.visBorderSystemIDs.discard(cur_system_id)
            neighbors = set(universe.getImmediateNeighbors(cur_system_id, empire_id))
            sys_status.setdefault('neighbors', set()).update(neighbors)
            if neighbors:
                status_info.append(" -- has neighbors %s" % sorted(neighbors))
                for sys_id in neighbors:
                    if sys_id not in aistate.exploredSystemIDs:
                        aistate.unexploredSystemIDs.add(sys_id)
                    if (sys_id not in graph_flags) and (sys_id not in aistate.visInteriorSystemIDs):
                        aistate.visBorderSystemIDs.add(sys_id)
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            debug('\n'.join(status_info))
            debug("----------------------------------------------------------")
Exemplo n.º 47
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)
Exemplo n.º 48
0
    def get_rating(self, enemy_stats=None, ignore_fighters=False):
        """Calculate a rating against specified enemy.

        If no enemy is specified, will rate against the empire standard enemy

        :param enemy_stats: Enemy stats to be rated against - if None
        :type enemy_stats: ShipCombatStats
        :param ignore_fighters: If True, acts as if fighters are not launched
        :type ignore_fighters: bool
        :return: rating against specified enemy
        :rtype: float
        """

        # adjust base stats according to enemy stats
        def _rating():
            return my_total_attack * my_structure

        # The fighter rating calculations are heavily based upon the enemy stats.
        # So, for now, we compare at least against a certain standard enemy.
        enemy_stats = enemy_stats or get_aistate().get_standard_enemy()

        my_attacks, my_structure, my_shields = self.get_basic_stats()
        # e_avg_attack = 1
        if enemy_stats:
            e_attacks, e_structure, e_shields = enemy_stats.get_basic_stats()
            if e_attacks:
                # e_num_attacks = sum(n for n in e_attacks.values())
                e_total_attack = sum(n * dmg for dmg, n in e_attacks.items())
                # e_avg_attack = e_total_attack / e_num_attacks
                e_net_attack = sum(n * max(dmg - my_shields, .001)
                                   for dmg, n in e_attacks.items())
                e_net_attack = max(e_net_attack, .1 * e_total_attack)
                shield_factor = e_total_attack / e_net_attack
                my_structure *= max(1, shield_factor)
            my_total_attack = sum(n * max(dmg - e_shields, .001)
                                  for dmg, n in my_attacks.items())
        else:
            my_total_attack = sum(n * dmg for dmg, n in my_attacks.items())
            my_structure += my_shields

        if ignore_fighters:
            return _rating()

        my_total_attack += self.estimate_fighter_damage()

        # TODO: Consider enemy fighters

        return _rating()
Exemplo n.º 49
0
    def print_resources_priority():
        """Calculate top resource priority."""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)
        debug("Resource Priorities:")
        resource_priorities = {}
        aistate = get_aistate()
        for priority_type in get_priority_resource_types():
            resource_priorities[priority_type] = aistate.get_priority(priority_type)

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

        # what is the focus of available resource centers?
        debug('')
        warnings = {}
        foci_table = Table([
                Text('Planet'),
                Text('Size'),
                Text('Type'),
                Text('Focus'),
                Text('Species'),
                Text('Pop')
            ], table_name="Planetary Foci Overview Turn %d" % fo.currentTurn())
        for pid in empire_planet_ids:
            planet = universe.getPlanet(pid)
            population = planet.currentMeterValue(fo.meterType.population)
            max_population = planet.currentMeterValue(fo.meterType.targetPopulation)
            if max_population < 1 and population > 0:
                warnings[planet.name] = (population, max_population)
            foci_table.add_row([
                planet,
                planet.size,
                planet.type,
                "_".join(str(planet.focus).split("_")[1:])[:8],
                planet.speciesName,
                "%.1f/%.1f" % (population, max_population)
            ])
        info(foci_table)
        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)
Exemplo n.º 50
0
def get_ship_id_with_role(fleet_id, ship_role, verbose=True):
    """Returns a ship with the specified role in the fleet."""

    if not fleet_has_ship_with_role(fleet_id, ship_role):
        if verbose:
            debug("No ship with role %s found." % ship_role)
        return None

    universe = fo.getUniverse()
    fleet = universe.getFleet(fleet_id)
    aistate = get_aistate()

    for ship_id in fleet.shipIDs:
        ship = universe.getShip(ship_id)
        if aistate.get_ship_role(ship.design.id) == ship_role:
            return ship_id
Exemplo n.º 51
0
def get_ship_id_with_role(fleet_id, ship_role, verbose=True):
    """Returns a ship with the specified role in the fleet."""

    if not fleet_has_ship_with_role(fleet_id, ship_role):
        if verbose:
            print "No ship with role %s found." % ship_role
        return None

    universe = fo.getUniverse()
    fleet = universe.getFleet(fleet_id)
    aistate = get_aistate()

    for ship_id in fleet.shipIDs:
        ship = universe.getShip(ship_id)
        if aistate.get_ship_role(ship.design.id) == ship_role:
            return ship_id
Exemplo n.º 52
0
 def issue_order(self):
     if not super(OrderMove, self).issue_order():
         return False
     fleet_id = self.fleet.id
     system_id = self.target.get_system().id
     fleet = self.fleet.get_object()
     if system_id not in [fleet.systemID, fleet.nextSystemID]:
         dest_id = system_id
         fo.issueFleetMoveOrder(fleet_id, dest_id)
         debug("Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target))
     aistate = get_aistate()
     if system_id == fleet.systemID:
         if aistate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
             if system_id in aistate.needsEmergencyExploration:
                 aistate.needsEmergencyExploration.remove(system_id)
     return True
Exemplo n.º 53
0
 def issue_order(self):
     if not super(OrderMove, self).issue_order():
         return False
     fleet_id = self.fleet.id
     system_id = self.target.get_system().id
     fleet = self.fleet.get_object()
     if system_id not in [fleet.systemID, fleet.nextSystemID]:
         dest_id = system_id
         fo.issueFleetMoveOrder(fleet_id, dest_id)
         print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)
     aistate = get_aistate()
     if system_id == fleet.systemID:
         if aistate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
             if system_id in aistate.needsEmergencyExploration:
                 aistate.needsEmergencyExploration.remove(system_id)
     return True
Exemplo n.º 54
0
    def can_issue_order(self, verbose=False):
        """If FleetOrder can be issued now."""
        # for some orders, may need to re-issue if invasion/outposting/colonization was interrupted
        if self.executed and not isinstance(self, (OrderOutpost, OrderColonize, OrderInvade)):
            return False
        if not self.is_valid():
            return False

        if verbose:
            sys1 = self.fleet.get_system()
            main_fleet_mission = get_aistate().get_fleet_mission(self.fleet.id)
            debug(
                "  Can issue %s - Mission Type %s (%s), current loc sys %d - %s"
                % (self, main_fleet_mission.type, main_fleet_mission.type, self.fleet.id, sys1)
            )
        return True
Exemplo n.º 55
0
def _calculate_top_production_queue_priority():
    """Calculates the top production queue priority."""
    production_queue_priorities = {}
    aistate = get_aistate()
    for priorityType in get_priority_production_types():
        production_queue_priorities[priorityType] = aistate.get_priority(
            priorityType)

    sorted_priorities = production_queue_priorities.items()
    sorted_priorities.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)
    top_production_queue_priority = -1
    for evaluationPair in sorted_priorities:
        if top_production_queue_priority < 0:
            top_production_queue_priority = evaluationPair[0]

    return top_production_queue_priority
Exemplo n.º 56
0
def startNewGame(aggression_input=fo.aggression.aggressive):  # pylint: disable=invalid-name
    """Called by client when a new game is started (but not when a game is loaded).
    Should clear any pre-existing state and set up whatever is needed for AI to generate orders."""
    empire = fo.getEmpire()
    if empire is None:
        fatal("This client has no empire. Ignoring new game start message.")
        return

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

    turn_timer.start("Server Processing")

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

    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()
Exemplo n.º 57
0
def _calculate_top_production_queue_priority():
    """Calculates the top production queue priority."""
    production_queue_priorities = {}
    aistate = get_aistate()
    for priorityType in get_priority_production_types():
        production_queue_priorities[priorityType] = aistate.get_priority(
            priorityType)

    sorted_priorities = sorted(production_queue_priorities.items(),
                               key=itemgetter(1),
                               reverse=True)
    top_production_queue_priority = -1
    for evaluationPair in sorted_priorities:
        if top_production_queue_priority < 0:
            top_production_queue_priority = evaluationPair[0]

    return top_production_queue_priority
Exemplo n.º 58
0
def assign_invasion_values(planet_ids):
    """Creates a dictionary that takes planet_ids as key and their invasion score as value."""
    empire_id = fo.empireID()
    planet_values = {}
    neighbor_values = {}
    neighbor_val_ratio = .95
    universe = fo.getUniverse()
    secure_missions = get_aistate().get_fleet_missions_with_any_mission_types(
        [MissionType.SECURE, MissionType.MILITARY])
    for pid in planet_ids:
        planet_values[pid] = neighbor_values.setdefault(
            pid, evaluate_invasion_planet(pid, secure_missions))
        debug("planet %d, values %s", pid, planet_values[pid])
        planet = universe.getPlanet(pid)
        species_name = (planet and planet.speciesName) or ""
        species = fo.getSpecies(species_name)
        if species and species.canProduceShips:
            system = universe.getSystem(planet.systemID)
            if not system:
                continue
            planet_industries = {}
            for pid2 in system.planetIDs:
                planet2 = universe.getPlanet(pid2)
                species_name2 = (planet2 and planet2.speciesName) or ""
                species2 = fo.getSpecies(species_name2)
                if species2 and species2.canProduceShips:
                    # to prevent divide-by-zero
                    planet_industries[pid2] = planet2.initialMeterValue(
                        fo.meterType.industry) + 0.1
            industry_ratio = planet_industries[pid] / max(
                planet_industries.values())
            for pid2 in system.planetIDs:
                if pid2 == pid:
                    continue
                planet2 = universe.getPlanet(pid2)
                # TODO check for allies
                if (planet2 and (planet2.owner != empire_id) and (
                    (planet2.owner != -1) or
                    (planet2.initialMeterValue(fo.meterType.population) > 0))):
                    planet_values[pid][0] += (
                        industry_ratio * neighbor_val_ratio *
                        (neighbor_values.setdefault(
                            pid2,
                            evaluate_invasion_planet(pid2,
                                                     secure_missions))[0]))
    return planet_values
Exemplo n.º 59
0
    def assign_base(self, fleet_id: int) -> bool:
        """
        Assign an outpost base fleet to execute the plan.

        It is expected that the fleet consists of only that one outpost base.

        :return: True on success, False on failure
        """
        if self.base_assigned:
            warning("Assigned a base to a plan that was already assigned a base to.")
            return False
        # give orders to perform the mission
        target = TargetPlanet(self.target)
        fleet_mission = get_aistate().get_fleet_mission(fleet_id)
        fleet_mission.set_target(MissionType.ORBITAL_OUTPOST, target)
        self.fleet_id = fleet_id
        return True