コード例 #1
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))
コード例 #2
0
ファイル: InvasionAI.py プロジェクト: adrianbroher/freeorion
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)
コード例 #3
0
ファイル: InvasionAI.py プロジェクト: simonsmall/freeorion
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)
コード例 #4
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))
コード例 #5
0
ファイル: AIFleetMission.py プロジェクト: foesi/freeorion
    def check_mergers(self, fleet_id=None, context=""):
        if fleet_id is None:
            fleet_id = self.fleet.id

        if self.type not in (MissionType.MILITARY,
                             MissionType.INVASION,
                             MissionType.ORBITAL_INVASION,
                             MissionType.SECURE,
                             MissionType.ORBITAL_DEFENSE,
                             ):
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == -1:
            return  # can't merge fleets in middle of starlane
        system_status = foAI.foAIstate.systemStatus[system_id]
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return  # nothing of record to merge with

        if not self.target:
            m_mt0_id = None
        else:
            m_mt0_id = self.target.id

        # TODO consider establishing an AI strategy & tactics planning document for discussing & planning
        # high level considerations for issues like fleet merger
        compatible_roles_map = {
            MissionType.ORBITAL_DEFENSE: [MissionType.ORBITAL_DEFENSE],
            MissionType.MILITARY: [MissionType.MILITARY],
            MissionType.ORBITAL_INVASION: [MissionType.ORBITAL_INVASION],
            MissionType.INVASION: [MissionType.INVASION],
        }

        main_fleet_role = foAI.foAIstate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = foAI.foAIstate.get_fleet_role(fid)
            if fleet_role not in compatible_roles_map[main_fleet_role]:  # TODO: if fleetRoles such as LongRange start being used, adjust this
                continue  # will only considering subsuming fleets that have a compatible role
            fleet = universe.getFleet(fid)
            if not (fleet and (fleet.systemID == system_id)):
                continue
            if not (fleet.speed > 0 or main_fleet.speed == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role == MissionType.ORBITAL_DEFENSE) or (fleet_role == MissionType.ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role == MissionType.ORBITAL_INVASION) or (fleet_role == MissionType.ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed > 0):
                do_merge = True
            else:
                if not self.target and (main_fleet.speed > 0 or fleet.speed == 0):
                    # print "\t\t\t ** Considering merging fleetA (id: %4d) into fleet (id %d) and former has no targets, will take it. FleetA mission was %s "%(fid, fleetID, fleet_mission)
                    do_merge = True
                else:
                    target = fleet_mission.target.id if fleet_mission.target else None
                    if target == m_mt0_id:
                        print "Military fleet %d has same target as %s fleet %d and will (at least temporarily) be merged into the latter" % (fid, fleet_role, fleet_id)
                        do_merge = True  # TODO: should probably ensure that fleetA has aggression on now
                    elif main_fleet.speed > 0:
                        neighbors = foAI.foAIstate.systemStatus.get(system_id, {}).get('neighbors', [])
                        if (target == system_id) and m_mt0_id in neighbors:  # consider 'borrowing' for work in neighbor system  # TODO check condition
                            if self.type in (MissionType.MILITARY,
                                             MissionType.SECURE):
                                # continue
                                if self.type == MissionType.SECURE:  # actually, currently this is probably the only one of all four that should really be possible in this situation
                                    need_left = 1.5 * sum([sysStat.get('fleetThreat', 0) for sysStat in
                                                           [foAI.foAIstate.systemStatus.get(neighbor, {}) for neighbor in
                                                                                                          [nid for nid in foAI.foAIstate.systemStatus.get(system_id, {}).get('neighbors', []) if nid != m_mt0_id]]])
                                    fb_rating = foAI.foAIstate.get_rating(fid)
                                    if (need_left < fb_rating.get('overall', 0)) and fb_rating.get('nships', 0) > 1:
                                        do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id, need_left,
                                                  context="Order %s of mission %s" % (context, self))
        return
コード例 #6
0
ファイル: AIFleetMission.py プロジェクト: foesi/freeorion
    def _check_retarget_invasion(self):
        """checks if an invasion mission should be retargeted"""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if fleet.systemID == -1:
            # next_loc = fleet.nextSystemID
            return  # TODO: still check
        system = universe.getSystem(fleet.systemID)
        if not system:
            return
        orders = self.orders
        last_sys_target = -1
        if orders:
            last_sys_target = orders[-1].target.id
        if last_sys_target == fleet.systemID:
            return  # TODO: check for best local target
        open_targets = []
        already_targeted = InvasionAI.get_invasion_targeted_planet_ids(system.planetIDs, MissionType.INVASION)
        for pid in system.planetIDs:
            if pid in already_targeted or (pid in foAI.foAIstate.qualifyingTroopBaseTargets):
                continue
            planet = universe.getPlanet(pid)
            if planet.unowned or (planet.owner == empire_id):
                continue
            if (planet.currentMeterValue(fo.meterType.shield)) <= 0:
                open_targets.append(pid)
        if not open_targets:
            return
        troops_in_fleet = FleetUtilsAI.count_troops_in_fleet(fleet_id)
        target_id = -1
        best_score = -1
        target_troops = 0
        #
        for pid, rating in InvasionAI.assign_invasion_values(open_targets, empire).items():
            p_score, p_troops = rating
            if p_score > best_score:
                if p_troops >= troops_in_fleet:
                    continue
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id == -1:
            return

        print "\t AIFleetMission._check_retarget_invasion: splitting and retargetting fleet %d" % fleet_id
        new_fleets = FleetUtilsAI.split_fleet(fleet_id)
        self.clear_target()  # TODO: clear from foAIstate
        self.clear_fleet_orders()
        # pods_needed = max(0, math.ceil((target_troops - 2 * (FleetUtilsAI.count_parts_fleetwide(fleet_id, ["GT_TROOP_POD"])) + 0.05) / 2.0))
        troops_needed = max(0, target_troops - FleetUtilsAI.count_troops_in_fleet(fleet_id))
        found_stats = {}
        min_stats = {'rating': 0, 'troopCapacity': troops_needed}
        target_stats = {'rating': 10, 'troopCapacity': troops_needed}
        found_fleets = []
        # TODO check if next statement does not mutate any global states and can be removed
        _ = FleetUtilsAI.get_fleets_for_mission(1, target_stats, min_stats, found_stats, "",
                                                systems_to_check=[fleet.systemID], systems_checked=[],
                                                fleet_pool_set=set(new_fleets), fleet_list=found_fleets,
                                                verbose=False)
        for fid in found_fleets:
            FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id)
        target = Planet(target_id)
        self.add_target(MissionType.INVASION, target)
        self.generate_fleet_orders()
コード例 #7
0
    def check_mergers(self, context=""):
        """
        If possible and reasonable, merge this fleet with others.

        :param context: Context of the function call for logging purposes
        :type context: str
        """
        if self.type not in MERGEABLE_MISSION_TYPES:
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == INVALID_ID:
            return  # can't merge fleets in middle of starlane
        system_status = foAI.foAIstate.systemStatus[system_id]
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return

        target_id = self.target.id if self.target else None
        main_fleet_role = foAI.foAIstate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = foAI.foAIstate.get_fleet_role(fid)
            if fleet_role not in COMPATIBLE_ROLES_MAP[main_fleet_role]:
                continue
            fleet = universe.getFleet(fid)

            if not fleet or fleet.systemID != system_id or len(fleet.shipIDs) == 0:
                continue
            if not (fleet.speed > 0 or main_fleet.speed == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role == MissionType.ORBITAL_DEFENSE) or (fleet_role == MissionType.ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role == MissionType.ORBITAL_INVASION) or (fleet_role == MissionType.ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed > 0):
                do_merge = True
            else:
                if not self.target and (main_fleet.speed > 0 or fleet.speed == 0):
                    do_merge = True
                else:
                    target = fleet_mission.target.id if fleet_mission.target else None
                    if target == target_id:
                        print "Military fleet %d has same target as %s fleet %d. Merging." % (fid, fleet_role, fleet_id)
                        do_merge = True  # TODO: should probably ensure that fleetA has aggression on now
                    elif main_fleet.speed > 0:
                        neighbors = foAI.foAIstate.systemStatus.get(system_id, {}).get('neighbors', [])
                        if target == system_id and target_id in neighbors and self.type == MissionType.SECURE:
                            # consider 'borrowing' for work in neighbor system  # TODO check condition
                            need_left = 1.5 * sum(foAI.foAIstate.systemStatus.get(nid, {}).get('fleetThreat', 0)
                                                  for nid in neighbors if nid != target_id)
                            fleet_rating = CombatRatingsAI.get_fleet_rating(fid)
                            if need_left < fleet_rating:
                                do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id, need_left,
                                                  context="Order %s of mission %s" % (context, self))
        return
コード例 #8
0
def assign_invasion_fleets_to_invade():
    """Assign fleet targets to invadable planets."""
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    fleet_suppliable_system_ids = empire.fleetSupplyableSystemIDs
    fleet_suppliable_planet_ids = PlanetUtilsAI.get_planets_in__systems_ids(fleet_suppliable_system_ids)

    all_troopbase_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.
                                                                        FLEET_MISSION_ORBITAL_INVASION)
    available_troopbase_fleet_ids = set(FleetUtilsAI.extract_fleet_ids_without_mission_types(all_troopbase_fleet_ids))
    for fid in list(available_troopbase_fleet_ids):
        if fid not in available_troopbase_fleet_ids:  # TODO: I do not see how this check makes sense, maybe remove?
            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(foAI.foAIstate.qualifyingTroopBaseTargets.keys()))
        print "Considering Base Troopers in %s, found planets %s and registered targets %s with status %s" % (
            system.name, list(system.planetIDs), available_planets,
            [(pid, foAI.foAIstate.qualifyingTroopBaseTargets[pid]) for pid in available_planets])
        targets = [pid for pid in available_planets if foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] != -1]
        if not targets:
            print "Error: found no valid target for troop base in system %s (%d)" % (system.name, sys_id)
            continue
        status = foAI.foAIstate.systemStatus.get(sys_id, {})
        local_base_troops = set(status.get('myfleets', [])).intersection(available_troopbase_fleet_ids)
        troop_capacity_tally = 0
        for fid2 in local_base_troops:
            troop_capacity_tally += FleetUtilsAI.count_troops_in_fleet(fid2)

        target_id = -1
        best_score = -1
        target_troops = 0
        for pid, rating in assign_invasion_values(targets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION,
                                                  fleet_suppliable_planet_ids, empire).items():
            p_score, p_troops = rating
            if p_score > best_score:
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id != -1:
            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}

            FleetUtilsAI.get_fleets_for_mission(1, target_stats, min_stats, found_stats, "",
                                                systems_to_check=[sys_id], systems_checked=[],
                                                fleet_pool_set=local_base_troops, fleet_list=found_fleets,
                                                verbose=False)
            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)
            foAI.foAIstate.qualifyingTroopBaseTargets[target_id][1] = -1  # TODO: should probably delete
            target = AITarget.AITarget(EnumsAI.TargetType.TARGET_PLANET, target_id)
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            fleet_mission.add_target(EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION, target)
    
    invasion_fleet_ids = AIstate.invasionFleetIDs

    send_invasion_fleets(invasion_fleet_ids, AIstate.invasionTargets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    for fid in FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids):
        this_mission = foAI.foAIstate.get_fleet_mission(fid)
        this_mission.check_mergers(context="Post-send consolidation of unassigned troops")
コード例 #9
0
def assign_invasion_fleets_to_invade():
    # assign fleet targets to invadable planets
    
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
    fleetSupplyablePlanetIDs = PlanetUtilsAI.get_planets_in__systems_ids(fleetSupplyableSystemIDs)

    allTroopBaseFleetIDs = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION)
    availTroopBaseFleetIDs = set(FleetUtilsAI.extract_fleet_ids_without_mission_types(allTroopBaseFleetIDs))
    for fid in list(availTroopBaseFleetIDs):
        if fid not in availTroopBaseFleetIDs:
            continue
        fleet = universe.getFleet(fid)
        if not fleet: 
            continue
        sysID = fleet.systemID
        system = universe.getSystem(sysID)
        availPlanets = set(system.planetIDs).intersection(set( foAI.foAIstate.qualifyingTroopBaseTargets.keys()))
        print "Considering Base Troopers in %s, found planets %s and regtistered targets %s with status %s"%(system.name, list(system.planetIDs), availPlanets,
                                                                                                           [(pid, foAI.foAIstate.qualifyingTroopBaseTargets[pid]) for pid in availPlanets])
        targets = [pid for pid in availPlanets if foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] != -1 ]
        if not targets:
            print "Error found no valid target for troop base in system %s (%d)"%(system.name, sysID)
            continue
        status=foAI.foAIstate.systemStatus.get( sysID, {} )
        local_base_troops = set(status.get('myfleets', [])).intersection(availTroopBaseFleetIDs)
        troop_pod_tally = 0
        for fid2 in local_base_troops:
            troop_pod_tally += FleetUtilsAI.count_parts_fleetwide(fid2, ["GT_TROOP_POD"])
        targetID=-1
        bestScore=-1
        target_troops = 0
        #
        for pid, rating in assign_invasion_values(targets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire).items():
            p_score, p_troops = rating
            if p_score>bestScore:
                if p_troops >= 2*troop_pod_tally:
                    pass
                    #continue
                bestScore = p_score
                targetID = pid
                target_troops = p_troops
        if targetID != -1:
            local_base_troops.discard(fid)
            foundFleets = []
            podsNeeded= math.ceil( (target_troops - 2*(FleetUtilsAI.count_parts_fleetwide(fid, ["GT_TROOP_POD"]))+0.05)/2.0)
            foundStats={}
            minStats= {'rating':0, 'troopPods':podsNeeded}
            targetStats={'rating':10,'troopPods':podsNeeded}
            theseFleets = FleetUtilsAI.get_fleets_for_mission(1, targetStats , minStats, foundStats, "", systems_to_check=[sysID], systems_checked=[], fleet_pool_set=local_base_troops, fleet_list=foundFleets, verbose=False)
            for fid2 in foundFleets:
                FleetUtilsAI.merge_fleet_a_into_b(fid2, fid)
                availTroopBaseFleetIDs.discard(fid2)
            availTroopBaseFleetIDs.discard(fid)
            foAI.foAIstate.qualifyingTroopBaseTargets[targetID][1] = -1 #TODO: should probably delete
            aiTarget = AITarget.AITarget(EnumsAI.TargetType.TARGET_PLANET, targetID)
            aiFleetMission = foAI.foAIstate.get_fleet_mission(fid)
            aiFleetMission.add_target(EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION, aiTarget)
    
    invasionFleetIDs = AIstate.invasionFleetIDs

    send_invasion_fleets(invasionFleetIDs, AIstate.invasionTargets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    allInvasionFleetIDs = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    for fid in FleetUtilsAI.extract_fleet_ids_without_mission_types(allInvasionFleetIDs):
        thisMission = foAI.foAIstate.get_fleet_mission(fid)
        thisMission.check_mergers(context="Post-send consolidation of unassigned troops")
コード例 #10
0
ファイル: AIFleetMission.py プロジェクト: sjb8100/freeorion
    def check_mergers(self, context=""):
        """
        If possible and reasonable, merge this fleet with others.

        :param context: Context of the function call for logging purposes
        :type context: str
        """
        if self.type not in MERGEABLE_MISSION_TYPES:
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == INVALID_ID:
            return  # can't merge fleets in middle of starlane
        aistate = get_aistate()
        system_status = aistate.systemStatus[system_id]

        # if a combat mission, and only have final order (so must be at final target), don't try
        # merging if there is no local threat (it tends to lead to fleet object churn)
        if self.type in COMBAT_MISSION_TYPES and len(
                self.orders) == 1 and not system_status.get('totalThreat', 0):
            return
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return

        target_id = self.target.id if self.target else None
        main_fleet_role = aistate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = aistate.get_fleet_role(fid)
            if fleet_role not in COMPATIBLE_ROLES_MAP[main_fleet_role]:
                continue
            fleet = universe.getFleet(fid)

            if not fleet or fleet.systemID != system_id or len(
                    fleet.shipIDs) == 0:
                continue
            if not (fleet.speed > 0 or main_fleet.speed
                    == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = aistate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role == MissionType.ORBITAL_DEFENSE) or (
                    fleet_role == MissionType.ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role == MissionType.ORBITAL_INVASION) or (
                    fleet_role == MissionType.ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed
                                                                   > 0):
                do_merge = True
            else:
                if not self.target and (main_fleet.speed > 0
                                        or fleet.speed == 0):
                    do_merge = True
                else:
                    target = fleet_mission.target.id if fleet_mission.target else None
                    if target == target_id:
                        info(
                            "Military fleet %d (%d ships) has same target as %s fleet %d (%d ships). Merging former "
                            "into latter." %
                            (fid, fleet.numShips, fleet_role, fleet_id,
                             len(main_fleet.shipIDs)))
                        # TODO: should probably ensure that fleetA has aggression on now
                        do_merge = float(min(
                            main_fleet.speed, fleet.speed)) / max(
                                main_fleet.speed, fleet.speed) >= 0.6
                    elif main_fleet.speed > 0:
                        neighbors = aistate.systemStatus.get(
                            system_id, {}).get('neighbors', [])
                        if target == system_id and target_id in neighbors and self.type == MissionType.SECURE:
                            # consider 'borrowing' for work in neighbor system  # TODO check condition
                            need_left = 1.5 * sum(
                                aistate.systemStatus.get(nid, {}).get(
                                    'fleetThreat', 0)
                                for nid in neighbors if nid != target_id)
                            fleet_rating = CombatRatingsAI.get_fleet_rating(
                                fid)
                            if need_left < fleet_rating:
                                do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(
                    fid,
                    fleet_id,
                    need_left,
                    context="Order %s of mission %s" % (context, self))
        return
コード例 #11
0
ファイル: InvasionAI.py プロジェクト: J-d-H/freeorion
def assign_invasion_fleets_to_invade():
    # assign fleet targets to invadable planets
    
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empireID = empire.empireID
    fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
    fleetSupplyablePlanetIDs = PlanetUtilsAI.get_planets_in__systems_ids(fleetSupplyableSystemIDs)

    allTroopBaseFleetIDs = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION)
    availTroopBaseFleetIDs = set(FleetUtilsAI.extract_fleet_ids_without_mission_types(allTroopBaseFleetIDs))
    for fid in list(availTroopBaseFleetIDs):
        if fid not in availTroopBaseFleetIDs:
            continue
        fleet = universe.getFleet(fid)
        if not fleet: 
            continue
        sysID = fleet.systemID
        system = universe.getSystem(sysID)
        availPlanets = set(system.planetIDs).intersection(set( foAI.foAIstate.qualifyingTroopBaseTargets.keys()))
        print "Considering Base Troopers in %s, found planets %s and regtistered targets %s with status %s"%(system.name, list(system.planetIDs), availPlanets,
                                                                                                           [(pid, foAI.foAIstate.qualifyingTroopBaseTargets[pid]) for pid in availPlanets])
        targets = [pid for pid in availPlanets if foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] != -1 ]
        if not targets:
            print "Error found no valid target for troop base in system %s (%d)"%(system.name, sysID)
            continue
        status=foAI.foAIstate.systemStatus.get( sysID, {} )
        local_base_troops = set(status.get('myfleets', [])).intersection(availTroopBaseFleetIDs)
        troop_pod_tally = 0
        for fid2 in local_base_troops:
            troop_pod_tally += FleetUtilsAI.count_parts_fleetwide(fid2, ["GT_TROOP_POD"])
        targetID=-1
        bestScore=-1
        target_troops = 0
        #
        for pid, rating in assign_invasion_values(targets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, fleetSupplyablePlanetIDs, empire).items():
            p_score, p_troops = rating
            if p_score>bestScore:
                if p_troops >= 2*troop_pod_tally:
                    pass
                    #continue
                bestScore = p_score
                targetID = pid
                target_troops = p_troops
        if targetID != -1:
            local_base_troops.discard(fid)
            foundFleets = []
            podsNeeded= math.ceil( (target_troops - 2*(FleetUtilsAI.count_parts_fleetwide(fid, ["GT_TROOP_POD"]))+0.05)/2.0)
            foundStats={}
            minStats= {'rating':0, 'troopPods':podsNeeded}
            targetStats={'rating':10,'troopPods':podsNeeded}
            theseFleets = FleetUtilsAI.get_fleets_for_mission(1, targetStats , minStats, foundStats, "", systems_to_check=[sysID], systems_checked=[], fleet_pool_set=local_base_troops, fleet_list=foundFleets, verbose=False)
            for fid2 in foundFleets:
                FleetUtilsAI.merge_fleet_a_into_b(fid2, fid)
                availTroopBaseFleetIDs.discard(fid2)
            availTroopBaseFleetIDs.discard(fid)
            foAI.foAIstate.qualifyingTroopBaseTargets[targetID][1] = -1 #TODO: should probably delete
            aiTarget = AITarget.AITarget(EnumsAI.AITargetType.TARGET_PLANET, targetID)
            aiFleetMission = foAI.foAIstate.get_fleet_mission(fid)
            aiFleetMission.add_target(EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION, aiTarget)
    
    invasionFleetIDs = AIstate.invasionFleetIDs

    send_invasion_fleets(invasionFleetIDs, AIstate.invasionTargets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    allInvasionFleetIDs = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    for fid in FleetUtilsAI.extract_fleet_ids_without_mission_types(allInvasionFleetIDs):
        thisMission = foAI.foAIstate.get_fleet_mission(fid)
        thisMission.check_mergers(context="Post-send consolidation of unassigned troops")
コード例 #12
0
ファイル: AIFleetMission.py プロジェクト: matthoppe/freeorion
    def check_mergers(self, fleet_id=None, context=""):
        if fleet_id is None:
            fleet_id = self.fleet.id

        if self.type not in (
                MissionType.MILITARY,
                MissionType.INVASION,
                MissionType.ORBITAL_INVASION,
                MissionType.SECURE,
                MissionType.ORBITAL_DEFENSE,
        ):
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == -1:
            return  # can't merge fleets in middle of starlane
        system_status = foAI.foAIstate.systemStatus[system_id]
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return  # nothing of record to merge with

        if not self.target:
            m_mt0_id = None
        else:
            m_mt0_id = self.target.id

        # TODO consider establishing an AI strategy & tactics planning document for discussing & planning
        # high level considerations for issues like fleet merger
        compatible_roles_map = {
            MissionType.ORBITAL_DEFENSE: [MissionType.ORBITAL_DEFENSE],
            MissionType.MILITARY: [MissionType.MILITARY],
            MissionType.ORBITAL_INVASION: [MissionType.ORBITAL_INVASION],
            MissionType.INVASION: [MissionType.INVASION],
        }

        main_fleet_role = foAI.foAIstate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = foAI.foAIstate.get_fleet_role(fid)
            if fleet_role not in compatible_roles_map[
                    main_fleet_role]:  # TODO: if fleetRoles such as LongRange start being used, adjust this
                continue  # will only considering subsuming fleets that have a compatible role
            fleet = universe.getFleet(fid)
            if not (fleet and (fleet.systemID == system_id)):
                continue
            if not (fleet.speed > 0 or main_fleet.speed
                    == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role == MissionType.ORBITAL_DEFENSE) or (
                    fleet_role == MissionType.ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role == MissionType.ORBITAL_INVASION) or (
                    fleet_role == MissionType.ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed
                                                                   > 0):
                do_merge = True
            else:
                if not self.target and (main_fleet.speed > 0
                                        or fleet.speed == 0):
                    # print "\t\t\t ** Considering merging fleetA (id: %4d) into fleet (id %d) and former has no targets, will take it. FleetA mission was %s "%(fid, fleetID, fleet_mission)
                    do_merge = True
                else:
                    target = fleet_mission.target.id if fleet_mission.target else None
                    if target == m_mt0_id:
                        print "Military fleet %d has same target as %s fleet %d and will (at least temporarily) be merged into the latter" % (
                            fid, fleet_role, fleet_id)
                        do_merge = True  # TODO: should probably ensure that fleetA has aggression on now
                    elif main_fleet.speed > 0:
                        neighbors = foAI.foAIstate.systemStatus.get(
                            system_id, {}).get('neighbors', [])
                        if (
                                target == system_id
                        ) and m_mt0_id in neighbors:  # consider 'borrowing' for work in neighbor system  # TODO check condition
                            if self.type in (MissionType.MILITARY,
                                             MissionType.SECURE):
                                # continue
                                if self.type == MissionType.SECURE:  # actually, currently this is probably the only one of all four that should really be possible in this situation
                                    need_left = 1.5 * sum([
                                        sysStat.get('fleetThreat', 0)
                                        for sysStat in [
                                            foAI.foAIstate.systemStatus.get(
                                                neighbor, {}) for neighbor in [
                                                    nid for nid in foAI.
                                                    foAIstate.systemStatus.get(
                                                        system_id, {}).get(
                                                            'neighbors', [])
                                                    if nid != m_mt0_id
                                                ]
                                        ]
                                    ])
                                    fb_rating = foAI.foAIstate.get_rating(fid)
                                    if (need_left < fb_rating.get(
                                            'overall', 0)) and fb_rating.get(
                                                'nships', 0) > 1:
                                        do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(
                    fid,
                    fleet_id,
                    need_left,
                    context="Order %s of mission %s" % (context, self))
        return
コード例 #13
0
ファイル: AIFleetMission.py プロジェクト: matthoppe/freeorion
    def _check_retarget_invasion(self):
        """checks if an invasion mission should be retargeted"""
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if fleet.systemID == -1:
            # next_loc = fleet.nextSystemID
            return  # TODO: still check
        system = universe.getSystem(fleet.systemID)
        if not system:
            return
        orders = self.orders
        last_sys_target = -1
        if orders:
            last_sys_target = orders[-1].target.id
        if last_sys_target == fleet.systemID:
            return  # TODO: check for best local target
        open_targets = []
        already_targeted = InvasionAI.get_invasion_targeted_planet_ids(
            system.planetIDs, MissionType.INVASION)
        for pid in system.planetIDs:
            if pid in already_targeted or (
                    pid in foAI.foAIstate.qualifyingTroopBaseTargets):
                continue
            planet = universe.getPlanet(pid)
            if planet.unowned or (planet.owner == empire_id):
                continue
            if (planet.currentMeterValue(fo.meterType.shield)) <= 0:
                open_targets.append(pid)
        if not open_targets:
            return
        troops_in_fleet = FleetUtilsAI.count_troops_in_fleet(fleet_id)
        target_id = -1
        best_score = -1
        target_troops = 0
        #
        for pid, rating in InvasionAI.assign_invasion_values(
                open_targets, empire).items():
            p_score, p_troops = rating
            if p_score > best_score:
                if p_troops >= troops_in_fleet:
                    continue
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id == -1:
            return

        print "\t AIFleetMission._check_retarget_invasion: splitting and retargetting fleet %d" % fleet_id
        new_fleets = FleetUtilsAI.split_fleet(fleet_id)
        self.clear_target()  # TODO: clear from foAIstate
        self.clear_fleet_orders()
        # pods_needed = max(0, math.ceil((target_troops - 2 * (FleetUtilsAI.count_parts_fleetwide(fleet_id, ["GT_TROOP_POD"])) + 0.05) / 2.0))
        troops_needed = max(
            0, target_troops - FleetUtilsAI.count_troops_in_fleet(fleet_id))
        found_stats = {}
        min_stats = {'rating': 0, 'troopCapacity': troops_needed}
        target_stats = {'rating': 10, 'troopCapacity': troops_needed}
        found_fleets = []
        # TODO check if next statement does not mutate any global states and can be removed
        _ = FleetUtilsAI.get_fleets_for_mission(
            1,
            target_stats,
            min_stats,
            found_stats,
            "",
            systems_to_check=[fleet.systemID],
            systems_checked=[],
            fleet_pool_set=set(new_fleets),
            fleet_list=found_fleets,
            verbose=False)
        for fid in found_fleets:
            FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id)
        target = Planet(target_id)
        self.add_target(MissionType.INVASION, target)
        self.generate_fleet_orders()
コード例 #14
0
    def check_mergers(self, fleet_id=None, context=""):
        if fleet_id is None:
            fleet_id = self.target_id

        mission_types = self.get_mission_types(
        )  # normally, currently, should only be one
        if len(mission_types) != 1:
            return  # if this fleet has multiple mission types, will not subsume other fleets
        mission_type = mission_types[0]
        if mission_type not in (
                AIFleetMissionType.FLEET_MISSION_ATTACK,
                AIFleetMissionType.FLEET_MISSION_DEFEND,
                AIFleetMissionType.FLEET_MISSION_LAST_STAND,
                AIFleetMissionType.FLEET_MISSION_MILITARY,
                AIFleetMissionType.FLEET_MISSION_INVASION,
                AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION,
                AIFleetMissionType.FLEET_MISSION_SECURE,
                AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE,
        ):
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == -1:
            return  # can't merge fleets in middle of starlane
        system_status = foAI.foAIstate.systemStatus[system_id]
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return  # nothing of record to merge with
        targets = self.get_targets(mission_type)
        if not targets:
            pass
            #return  #let's let invasion fleets with no target get merged
            m_MT0_id = None
        else:
            m_MT0_id = targets[0].target_id
        if len(targets) > 1:
            pass
            print "\tConsidering merging fleets into fleet %d, but it has multiple targets: %s" % (
                fleet_id, str(targets))
        # TODO (Cjkjvfnby) check why we cant merge fleet with other missions to each other
        # TODO consider establishing an AI strategy & tactics planning document for discussing & planning
        # high level considerations for issues like fleet merger
        compatibileRolesMap = {
            EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE:
            [EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE],
            EnumsAI.AIFleetMissionType.FLEET_MISSION_MILITARY:
            [EnumsAI.AIFleetMissionType.FLEET_MISSION_MILITARY],
            EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION:
            [EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION],
            EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION:
            [EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION],
        }

        main_fleet_role = foAI.foAIstate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = foAI.foAIstate.get_fleet_role(fid)
            if fleet_role not in compatibileRolesMap[
                    main_fleet_role]:  # TODO: if fleetRoles such as LongRange start being used, adjust this
                continue  # will only considering subsuming fleets that have a compatible role
            fleet = universe.getFleet(fid)
            if not (fleet and (fleet.systemID == system_id)):
                continue
            if not (fleet.speed > 0 or main_fleet.speed
                    == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role
                    == AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE) or (
                        fleet_role
                        == AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role
                  == AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION) or (
                      fleet_role
                      == AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed
                                                                   > 0):
                do_merge = True
            else:
                fleet_mission_type = fleet_mission.get_mission_types(
                )[0] if fleet_mission.get_mission_types(
                ) else AIFleetMissionType.FLEET_MISSION_INVALID
                fleet_targets = fleet_mission.get_targets(fleet_mission_type)
                if len(fleet_targets) > 1:
                    pass
                elif not fleet_targets and (main_fleet.speed > 0
                                            or fleet.speed == 0):
                    #print "\t\t\t ** Considering merging fleetA (id: %4d) into fleet (id %d) and former has no targets, will take it. FleetA mission was %s "%(fid, fleetID, fleet_mission)
                    do_merge = True
                else:
                    target = fleet_targets[0].target_id
                    if target == m_MT0_id:
                        print "Military fleet %d has same target as %s fleet %d and will (at least temporarily) be merged into the latter" % (
                            fid, EnumsAI.AIShipRoleType.name(fleet_role),
                            fleet_id)
                        do_merge = True  # TODO: should probably ensure that fleetA has aggression on now
                    elif main_fleet.speed > 0:
                        neighbors = foAI.foAIstate.systemStatus.get(
                            system_id, {}).get('neighbors', [])
                        if (
                                target == system_id
                        ) and m_MT0_id in neighbors:  # consider 'borrowing' for work in neighbor system  # TODO check condition
                            if fleet_mission_type in (
                                    AIFleetMissionType.FLEET_MISSION_ATTACK,
                                    AIFleetMissionType.FLEET_MISSION_DEFEND,
                                    AIFleetMissionType.FLEET_MISSION_MILITARY,
                                    AIFleetMissionType.FLEET_MISSION_SECURE):
                                #continue
                                if fleet_mission_type in (
                                        AIFleetMissionType.
                                        FLEET_MISSION_DEFEND,
                                        AIFleetMissionType.
                                        FLEET_MISSION_SECURE,  # actually, currently this is probably the onle one of all four that should really be possibile in this situation
                                ):
                                    need_left = 1.5 * sum([
                                        sysStat.get('fleetThreat', 0)
                                        for sysStat in [
                                            foAI.foAIstate.systemStatus.get(
                                                neighbor, {}) for neighbor in [
                                                    nid for nid in foAI.
                                                    foAIstate.systemStatus.get(
                                                        system_id, {}).get(
                                                            'neighbors', [])
                                                    if nid != m_MT0_id
                                                ]
                                        ]
                                    ])
                                    fBRating = foAI.foAIstate.get_rating(fid)
                                    if (need_left < fBRating.get('overall', 0)
                                        ) and fBRating.get('nships', 0) > 1:
                                        do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(
                    fid,
                    fleet_id,
                    need_left,
                    context="Order %s of mission %s" % (context, self))
        return
コード例 #15
0
ファイル: AIFleetMission.py プロジェクト: J-d-H/freeorion
    def check_mergers(self, fleet_id=None, context=""):
        if fleet_id is None:
            fleet_id = self.target_id

        mission_types = self.get_mission_types()  # normally, currently, should only be one
        if len(mission_types) != 1:
            return  # if this fleet has multiple mission types, will not subsume other fleets
        mission_type = mission_types[0]
        if mission_type not in (AIFleetMissionType.FLEET_MISSION_ATTACK,
                                AIFleetMissionType.FLEET_MISSION_DEFEND,
                                AIFleetMissionType.FLEET_MISSION_LAST_STAND,
                                AIFleetMissionType.FLEET_MISSION_MILITARY,
                                AIFleetMissionType.FLEET_MISSION_INVASION,
                                AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION,
                                AIFleetMissionType.FLEET_MISSION_SECURE,
                                AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE,
                                ):
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == -1:
            return  # can't merge fleets in middle of starlane
        system_status = foAI.foAIstate.systemStatus[system_id]
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return  # nothing of record to merge with
        targets = self.get_targets(mission_type)
        if not targets:
            pass
            #return  #let's let invasion fleets with no target get merged
            m_MT0_id = None
        else:
            m_MT0_id = targets[0].target_id
        if len(targets) > 1:
            pass
            print "\tConsidering merging fleets into fleet %d, but it has multiple targets: %s" % (fleet_id, str(targets))
        # TODO (Cjkjvfnby) check why we cant merge fleet with other missions to each other
        # TODO consider establishing an AI strategy & tactics planning document for discussing & planning
        # high level considerations for issues like fleet merger
        compatibileRolesMap = {EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE: [EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE],
                               EnumsAI.AIFleetMissionType.FLEET_MISSION_MILITARY: [EnumsAI.AIFleetMissionType.FLEET_MISSION_MILITARY],
                               EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION: [EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION],
                               EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION: [EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION],
                               }

        main_fleet_role = foAI.foAIstate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = foAI.foAIstate.get_fleet_role(fid)
            if fleet_role not in compatibileRolesMap[main_fleet_role]:  # TODO: if fleetRoles such as LongRange start being used, adjust this
                continue  # will only considering subsuming fleets that have a compatible role
            fleet = universe.getFleet(fid)
            if not (fleet and (fleet.systemID == system_id)):
                continue
            if not (fleet.speed > 0 or main_fleet.speed == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role == AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE) or (fleet_role == AIFleetMissionType.FLEET_MISSION_ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role == AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION) or (fleet_role == AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed > 0):
                do_merge = True
            else:
                fleet_mission_type = fleet_mission.get_mission_types()[0] if fleet_mission.get_mission_types() else AIFleetMissionType.FLEET_MISSION_INVALID
                fleet_targets = fleet_mission.get_targets(fleet_mission_type)
                if len(fleet_targets) > 1:
                    pass
                elif not fleet_targets and (main_fleet.speed > 0 or fleet.speed == 0):
                    #print "\t\t\t ** Considering merging fleetA (id: %4d) into fleet (id %d) and former has no targets, will take it. FleetA mission was %s "%(fid, fleetID, fleet_mission)
                    do_merge = True
                else:
                    target = fleet_targets[0].target_id
                    if target == m_MT0_id:
                        print "Military fleet %d has same target as %s fleet %d and will (at least temporarily) be merged into the latter" % (fid, EnumsAI.AIShipRoleType.name(fleet_role), fleet_id)
                        do_merge = True  # TODO: should probably ensure that fleetA has aggression on now
                    elif main_fleet.speed > 0:
                        neighbors = foAI.foAIstate.systemStatus.get(system_id, {}).get('neighbors', [])
                        if (target == system_id) and m_MT0_id in neighbors:  # consider 'borrowing' for work in neighbor system  # TODO check condition
                            if fleet_mission_type in (AIFleetMissionType.FLEET_MISSION_ATTACK,
                                                      AIFleetMissionType.FLEET_MISSION_DEFEND,
                                                      AIFleetMissionType.FLEET_MISSION_MILITARY,
                                                      AIFleetMissionType.FLEET_MISSION_SECURE):
                                #continue
                                if fleet_mission_type in (AIFleetMissionType.FLEET_MISSION_DEFEND,
                                                          AIFleetMissionType.FLEET_MISSION_SECURE,  # actually, currently this is probably the onle one of all four that should really be possibile in this situation
                                                          ):
                                    need_left = 1.5 * sum([sysStat.get('fleetThreat', 0) for sysStat in
                                                           [foAI.foAIstate.systemStatus.get(neighbor, {}) for neighbor in
                                                                                                          [nid for nid in foAI.foAIstate.systemStatus.get(system_id, {}).get('neighbors', []) if nid != m_MT0_id]]])
                                    fBRating = foAI.foAIstate.get_rating(fid)
                                    if (need_left < fBRating.get('overall', 0)) and fBRating.get('nships', 0) > 1:
                                        do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id, need_left,
                                                  context="Order %s of mission %s" % (context, self))
        return
コード例 #16
0
    def _check_retarget_invasion(self):
        """checks if an invasion mission should be retargeted"""
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if fleet.systemID == INVALID_ID:
            # next_loc = fleet.nextSystemID
            return  # TODO: still check
        system = universe.getSystem(fleet.systemID)
        if not system:
            return
        orders = self.orders
        last_sys_target = INVALID_ID
        if orders:
            last_sys_target = orders[-1].target.id
        if last_sys_target == fleet.systemID:
            return  # TODO: check for best local target
        open_targets = []
        already_targeted = InvasionAI.get_invasion_targeted_planet_ids(system.planetIDs, MissionType.INVASION)
        aistate = get_aistate()
        for pid in system.planetIDs:
            if pid in already_targeted or (pid in aistate.qualifyingTroopBaseTargets):
                continue
            planet = universe.getPlanet(pid)
            if planet.unowned or (planet.owner == empire_id):
                continue
            if (planet.initialMeterValue(fo.meterType.shield)) <= 0:
                open_targets.append(pid)
        if not open_targets:
            return
        troops_in_fleet = FleetUtilsAI.count_troops_in_fleet(fleet_id)
        target_id = INVALID_ID
        best_score = -1
        target_troops = 0
        #
        for pid, rating in InvasionAI.assign_invasion_values(open_targets).items():
            p_score, p_troops = rating
            if p_score > best_score:
                if p_troops >= troops_in_fleet:
                    continue
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id == INVALID_ID:
            return

        debug("\t Splitting and retargetting fleet %d" % fleet_id)
        new_fleets = FleetUtilsAI.split_fleet(fleet_id)
        self.clear_target()  # TODO: clear from foAIstate
        self.clear_fleet_orders()
        troops_needed = max(0, target_troops - FleetUtilsAI.count_troops_in_fleet(fleet_id))
        min_stats = {'rating': 0, 'troopCapacity': troops_needed}
        target_stats = {'rating': 10, 'troopCapacity': troops_needed}
        found_fleets = []
        # TODO check if next statement does not mutate any global states and can be removed

        _ = FleetUtilsAI.get_fleets_for_mission(target_stats, min_stats, {}, starting_system=fleet.systemID,  # noqa: F841
                                                fleet_pool_set=set(new_fleets), fleet_list=found_fleets)
        for fid in found_fleets:
            FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id)
        target = TargetPlanet(target_id)
        self.set_target(MissionType.INVASION, target)
        self.generate_fleet_orders()
コード例 #17
0
ファイル: InvasionAI.py プロジェクト: adityavs/freeorion
def assign_invasion_fleets_to_invade():
    """Assign fleet targets to invadable planets."""
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    fleet_suppliable_system_ids = empire.fleetSupplyableSystemIDs
    fleet_suppliable_planet_ids = PlanetUtilsAI.get_planets_in__systems_ids(fleet_suppliable_system_ids)

    all_troopbase_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.
                                                                        FLEET_MISSION_ORBITAL_INVASION)
    available_troopbase_fleet_ids = set(FleetUtilsAI.extract_fleet_ids_without_mission_types(all_troopbase_fleet_ids))
    for fid in list(available_troopbase_fleet_ids):
        if fid not in available_troopbase_fleet_ids:  # TODO: I do not see how this check makes sense, maybe remove?
            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(foAI.foAIstate.qualifyingTroopBaseTargets.keys()))
        print "Considering Base Troopers in %s, found planets %s and registered targets %s with status %s" % (
            system.name, list(system.planetIDs), available_planets,
            [(pid, foAI.foAIstate.qualifyingTroopBaseTargets[pid]) for pid in available_planets])
        targets = [pid for pid in available_planets if foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] != -1]
        if not targets:
            print "Error: found no valid target for troop base in system %s (%d)" % (system.name, sys_id)
            continue
        status = foAI.foAIstate.systemStatus.get(sys_id, {})
        local_base_troops = set(status.get('myfleets', [])).intersection(available_troopbase_fleet_ids)
        troop_capacity_tally = 0
        for fid2 in local_base_troops:
            troop_capacity_tally += FleetUtilsAI.count_troops_in_fleet(fid2)

        target_id = -1
        best_score = -1
        target_troops = 0
        for pid, rating in assign_invasion_values(targets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION,
                                                  fleet_suppliable_planet_ids, empire).items():
            p_score, p_troops = rating
            if p_score > best_score:
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id != -1:
            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}

            FleetUtilsAI.get_fleets_for_mission(1, target_stats, min_stats, found_stats, "",
                                                systems_to_check=[sys_id], systems_checked=[],
                                                fleet_pool_set=local_base_troops, fleet_list=found_fleets,
                                                verbose=False)
            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)
            foAI.foAIstate.qualifyingTroopBaseTargets[target_id][1] = -1  # TODO: should probably delete
            target = AITarget.AITarget(EnumsAI.TargetType.TARGET_PLANET, target_id)
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            fleet_mission.add_target(EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION, target)
    
    invasion_fleet_ids = AIstate.invasionFleetIDs

    send_invasion_fleets(invasion_fleet_ids, AIstate.invasionTargets, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    for fid in FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids):
        this_mission = foAI.foAIstate.get_fleet_mission(fid)
        this_mission.check_mergers(context="Post-send consolidation of unassigned troops")
コード例 #18
0
ファイル: AIFleetMission.py プロジェクト: sjb8100/freeorion
    def _check_retarget_invasion(self):
        """checks if an invasion mission should be retargeted"""
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if fleet.systemID == INVALID_ID:
            # next_loc = fleet.nextSystemID
            return  # TODO: still check
        system = universe.getSystem(fleet.systemID)
        if not system:
            return
        orders = self.orders
        last_sys_target = INVALID_ID
        if orders:
            last_sys_target = orders[-1].target.id
        if last_sys_target == fleet.systemID:
            return  # TODO: check for best local target
        open_targets = []
        already_targeted = InvasionAI.get_invasion_targeted_planet_ids(
            system.planetIDs, MissionType.INVASION)
        aistate = get_aistate()
        for pid in system.planetIDs:
            if pid in already_targeted or (
                    pid in aistate.qualifyingTroopBaseTargets):
                continue
            planet = universe.getPlanet(pid)
            if planet.unowned or (planet.owner == empire_id):
                continue
            if (planet.initialMeterValue(fo.meterType.shield)) <= 0:
                open_targets.append(pid)
        if not open_targets:
            return
        troops_in_fleet = FleetUtilsAI.count_troops_in_fleet(fleet_id)
        target_id = INVALID_ID
        best_score = -1
        target_troops = 0
        #
        for pid, rating in InvasionAI.assign_invasion_values(
                open_targets).items():
            p_score, p_troops = rating
            if p_score > best_score:
                if p_troops >= troops_in_fleet:
                    continue
                best_score = p_score
                target_id = pid
                target_troops = p_troops
        if target_id == INVALID_ID:
            return

        debug("\t Splitting and retargetting fleet %d" % fleet_id)
        new_fleets = FleetUtilsAI.split_fleet(fleet_id)
        self.clear_target()  # TODO: clear from foAIstate
        self.clear_fleet_orders()
        troops_needed = max(
            0, target_troops - FleetUtilsAI.count_troops_in_fleet(fleet_id))
        min_stats = {'rating': 0, 'troopCapacity': troops_needed}
        target_stats = {'rating': 10, 'troopCapacity': troops_needed}
        found_fleets = []
        # TODO check if next statement does not mutate any global states and can be removed

        _ = FleetUtilsAI.get_fleets_for_mission(
            target_stats,
            min_stats,
            {},
            starting_system=fleet.systemID,  # noqa: F841
            fleet_pool_set=set(new_fleets),
            fleet_list=found_fleets)
        for fid in found_fleets:
            FleetUtilsAI.merge_fleet_a_into_b(fid, fleet_id)
        target = TargetPlanet(target_id)
        self.set_target(MissionType.INVASION, target)
        self.generate_fleet_orders()
コード例 #19
0
    def check_mergers(self, context=""):
        """
        If possible and reasonable, merge this fleet with others.

        :param context: Context of the function call for logging purposes
        :type context: str
        """
        if self.type not in MERGEABLE_MISSION_TYPES:
            return
        universe = fo.getUniverse()
        empire_id = fo.empireID()
        fleet_id = self.fleet.id
        main_fleet = universe.getFleet(fleet_id)
        system_id = main_fleet.systemID
        if system_id == -1:
            return  # can't merge fleets in middle of starlane
        system_status = foAI.foAIstate.systemStatus[system_id]
        destroyed_list = list(universe.destroyedObjectIDs(empire_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:
            return

        target_id = self.target.id if self.target else None
        main_fleet_role = foAI.foAIstate.get_fleet_role(fleet_id)
        for fid in other_fleets_here:
            fleet_role = foAI.foAIstate.get_fleet_role(fid)
            if fleet_role not in COMPATIBLE_ROLES_MAP[main_fleet_role]:
                continue
            fleet = universe.getFleet(fid)
            if not fleet or fleet.systemID != system_id:
                continue
            if not (fleet.speed > 0 or main_fleet.speed
                    == 0):  # TODO(Cjkjvfnby) Check this condition
                continue
            fleet_mission = foAI.foAIstate.get_fleet_mission(fid)
            do_merge = False
            need_left = 0
            if (main_fleet_role == MissionType.ORBITAL_DEFENSE) or (
                    fleet_role == MissionType.ORBITAL_DEFENSE):
                if main_fleet_role == fleet_role:
                    do_merge = True
            elif (main_fleet_role == MissionType.ORBITAL_INVASION) or (
                    fleet_role == MissionType.ORBITAL_INVASION):
                if main_fleet_role == fleet_role:
                    do_merge = False  # TODO: could allow merger if both orb invaders and both same target
            elif not fleet_mission and (main_fleet.speed > 0) and (fleet.speed
                                                                   > 0):
                do_merge = True
            else:
                if not self.target and (main_fleet.speed > 0
                                        or fleet.speed == 0):
                    do_merge = True
                else:
                    target = fleet_mission.target.id if fleet_mission.target else None
                    if target == target_id:
                        print "Military fleet %d has same target as %s fleet %d. Merging." % (
                            fid, fleet_role, fleet_id)
                        do_merge = True  # TODO: should probably ensure that fleetA has aggression on now
                    elif main_fleet.speed > 0:
                        neighbors = foAI.foAIstate.systemStatus.get(
                            system_id, {}).get('neighbors', [])
                        if target == system_id and target_id in neighbors and self.type == MissionType.SECURE:
                            # consider 'borrowing' for work in neighbor system  # TODO check condition
                            need_left = 1.5 * sum(
                                foAI.foAIstate.systemStatus.get(nid, {}).get(
                                    'fleetThreat', 0)
                                for nid in neighbors if nid != target_id)
                            fb_rating = foAI.foAIstate.get_rating(fid)
                            if (need_left < fb_rating.get('overall', 0)
                                ) and fb_rating.get('nships', 0) > 1:
                                do_merge = True
            if do_merge:
                FleetUtilsAI.merge_fleet_a_into_b(
                    fid,
                    fleet_id,
                    need_left,
                    context="Order %s of mission %s" % (context, self))
        return