Ejemplo n.º 1
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    exploration_list = [start_system_id]
    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 foAI.foAIstate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in foAI.foAIstate.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)
            print "%s previously %s. Visibility per turn: %s " % (
                system_header, pre_vis, visibility_info)
            status_info = []
        else:
            status_info = [system_header]

        has_been_visible = universe.getVisibilityTurnsMap(
            cur_system_id, empire_id).get(fo.visibility.partial, 0) > 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 = foAI.foAIstate.systemStatus.setdefault(
                cur_system_id, {})
            foAI.foAIstate.visInteriorSystemIDs.add(cur_system_id)
            foAI.foAIstate.visBorderSystemIDs.discard(cur_system_id)
            neighbors = set(
                dict_from_map(
                    universe.getSystemNeighborsMap(cur_system_id,
                                                   empire_id)).keys())
            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 foAI.foAIstate.exploredSystemIDs:
                        foAI.foAIstate.unexploredSystemIDs.add(sys_id)
                    if (sys_id not in graph_flags) and (
                            sys_id not in foAI.foAIstate.visInteriorSystemIDs):
                        foAI.foAIstate.visBorderSystemIDs.add(sys_id)
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            print '\n'.join(status_info)
            print "----------------------------------------------------------"
Ejemplo n.º 2
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = fo.empireID()
    exploration_list = [start_system_id]
    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 foAI.foAIstate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in foAI.foAIstate.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)
            print "%s previously %s. Visibility per turn: %s " % (system_header, pre_vis, visibility_info)
            status_info = []
        else:
            status_info = [system_header]

        has_been_visible = universe.getVisibilityTurnsMap(cur_system_id, empire_id).get(fo.visibility.partial, 0) > 0
        is_connected = universe.systemsConnected(cur_system_id, home_system_id, -1)  # self.empire_id)
        status_info.append("    -- is%s partially visible" % ([" not", ""][has_been_visible]))
        status_info.append("    -- is%s visibly connected to homesystem" % ([" not", ""][is_connected]))
        if has_been_visible:
            sys_status = foAI.foAIstate.systemStatus.setdefault(cur_system_id, {})
            foAI.foAIstate.visInteriorSystemIDs.add(cur_system_id)
            foAI.foAIstate.visBorderSystemIDs.discard(cur_system_id)
            neighbors = set(dict_from_map(universe.getSystemNeighborsMap(cur_system_id, empire_id)).keys())
            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 foAI.foAIstate.exploredSystemIDs:
                        foAI.foAIstate.unexploredSystemIDs.add(sys_id)
                    if (sys_id not in graph_flags) and (sys_id not in foAI.foAIstate.visInteriorSystemIDs):
                        foAI.foAIstate.visBorderSystemIDs.add(sys_id)
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            print '\n'.join(status_info)
            print "----------------------------------------------------------"
def int_int_map_to_string(int_int_map):
    return str(dict_from_map(int_int_map))
Ejemplo n.º 4
0
    def update_system_status(self):
        print 10 * "=", "Updating System Threats", 10 * "="
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_id = fo.empireID()
        destroyed_object_ids = universe.destroyedObjectIDs(empire_id)
        supply_unobstructed_systems = set(empire.supplyUnobstructedSystems)
        min_hidden_attack = 4
        min_hidden_health = 8
        system_id_list = universe.systemIDs  # will normally look at this, the list of all known systems

        # for use in debugging
        verbose = False

        # assess enemy fleets that may have been momentarily visible
        cur_e_fighters = {CombatRatingsAI.default_ship_stats().get_stats(hashable=True): [0]}  # start with a dummy entry
        old_e_fighters = {CombatRatingsAI.default_ship_stats().get_stats(hashable=True): [0]}  # start with a dummy entry
        enemy_fleet_ids = []
        enemies_by_system = {}
        my_fleets_by_system = {}
        fleet_spot_position = {}
        saw_enemies_at_system = {}
        my_milship_rating = MilitaryAI.cur_best_mil_ship_rating()
        current_turn = fo.currentTurn()
        for fleet_id in universe.fleetIDs:
            fleet = universe.getFleet(fleet_id)
            if fleet is None:
                continue
            if not fleet.empty:
                # TODO: check if currently in system and blockaded before accepting destination as location
                this_system_id = (fleet.nextSystemID != INVALID_ID and fleet.nextSystemID) or fleet.systemID
                if fleet.ownedBy(empire_id):
                    if fleet_id not in destroyed_object_ids:
                        my_fleets_by_system.setdefault(this_system_id, []).append(fleet_id)
                        fleet_spot_position.setdefault(fleet.systemID, []).append(fleet_id)
                else:
                    dead_fleet = fleet_id in destroyed_object_ids
                    if not fleet.ownedBy(-1) and (fleet.hasArmedShips or fleet.hasFighterShips):
                        ship_stats = CombatRatingsAI.FleetCombatStats(fleet_id).get_ship_stats(hashable=True)
                        e_f_dict = [cur_e_fighters, old_e_fighters][dead_fleet]  # track old/dead enemy fighters for rating assessments in case not enough current info
                        for stats in ship_stats:
                            attacks = stats[0]
                            if attacks:
                                e_f_dict.setdefault(stats, [0])[0] += 1
                    partial_vis_turn = universe.getVisibilityTurnsMap(fleet_id, empire_id).get(fo.visibility.partial, -9999)
                    if not dead_fleet:
                        # TODO: consider checking death of individual ships.  If ships had been moved from this fleet
                        # into another fleet, we might have witnessed their death in that other fleet but if this fleet
                        # had not been seen since before that transfer then the ships might also still be listed here.
                        sys_status = self.systemStatus.setdefault(this_system_id, {})
                        sys_status['enemy_ship_count'] = sys_status.get('enemy_ship_count', 0) + len(fleet.shipIDs)
                        if partial_vis_turn >= current_turn - 1:  # only interested in immediately recent data
                            saw_enemies_at_system[fleet.systemID] = True
                            enemy_fleet_ids.append(fleet_id)
                            enemies_by_system.setdefault(this_system_id, []).append(fleet_id)
                            if not fleet.ownedBy(-1):
                                self.misc.setdefault('enemies_sighted', {}).setdefault(current_turn, []).append(fleet_id)
                                rating = CombatRatingsAI.get_fleet_rating(fleet_id, enemy_stats=CombatRatingsAI.get_empire_standard_fighter())
                                if rating > 0.25 * my_milship_rating:
                                    self.misc.setdefault('dangerous_enemies_sighted', {}).setdefault(current_turn, []).append(fleet_id)
        e_f_dict = [cur_e_fighters, old_e_fighters][len(cur_e_fighters) == 1]
        std_fighter = sorted([(v, k) for k, v in e_f_dict.items()])[-1][1]
        self.__empire_standard_enemy = std_fighter
        self.empire_standard_enemy_rating = self.get_standard_enemy().get_rating()
        # TODO: If no current information available, rate against own fighters

        # assess fleet and planet threats & my local fleets
        for sys_id in system_id_list:
            sys_status = self.systemStatus.setdefault(sys_id, {})
            system = universe.getSystem(sys_id)
            if verbose:
                print "AIState threat evaluation for %s" % system
            # update fleets
            sys_status['myfleets'] = my_fleets_by_system.get(sys_id, [])
            sys_status['myFleetsAccessible'] = fleet_spot_position.get(sys_id, [])
            local_enemy_fleet_ids = enemies_by_system.get(sys_id, [])
            sys_status['localEnemyFleetIDs'] = local_enemy_fleet_ids
            if system:
                sys_status['name'] = system.name
                for fid in system.fleetIDs:
                    if fid in destroyed_object_ids:  # TODO: double check are these checks/deletes necessary?
                        self.delete_fleet_info(fid)  # this is safe even if fleet wasn't mine
                        continue
                    fleet = universe.getFleet(fid)
                    if not fleet or fleet.empty:
                        self.delete_fleet_info(fid)  # this is safe even if fleet wasn't mine
                        continue

            # update threats
            sys_vis_dict = universe.getVisibilityTurnsMap(sys_id, fo.empireID())
            partial_vis_turn = sys_vis_dict.get(fo.visibility.partial, -9999)
            mob_ratings = []  # for mobile unowned monster fleets
            lost_fleet_rating = 0
            enemy_ratings = []
            monster_ratings = []
            mobile_fleets = []
            for fid in local_enemy_fleet_ids:
                fleet = universe.getFleet(fid)
                if not fleet:
                    continue
                fleet_rating = CombatRatingsAI.get_fleet_rating(fid, enemy_stats=CombatRatingsAI.get_empire_standard_fighter())
                if fleet.speed == 0:
                    monster_ratings.append(fleet_rating)
                    if verbose:
                        print "\t immobile enemy fleet %s has rating %.1f" % (fleet, fleet_rating)
                else:
                    if verbose:
                        print "\t mobile enemy fleet %s has rating %.1f" % (fleet, fleet_rating)
                    mobile_fleets.append(fid)
                    if fleet.unowned:
                        mob_ratings.append(fleet_rating)
                    else:
                        enemy_ratings.append(fleet_rating)
            enemy_rating = CombatRatingsAI.combine_ratings_list(enemy_ratings)
            monster_rating = CombatRatingsAI.combine_ratings_list(monster_ratings)
            mob_rating = CombatRatingsAI.combine_ratings_list(mob_ratings)
            if fleetsLostBySystem.get(sys_id, []):
                lost_fleet_rating = CombatRatingsAI.combine_ratings_list(fleetsLostBySystem[sys_id])
            if not system or partial_vis_turn == -9999:  # under current visibility rules should not be possible to have any losses or other info here, but just in case...
                if verbose:
                    print "Have never had partial vis for system %d ( %s ) -- basing threat assessment on old info and lost ships" % (sys_id, sys_status.get('name', "name unknown"))
                sys_status.setdefault('local_fleet_threats', set())
                sys_status['planetThreat'] = 0
                sys_status['fleetThreat'] = int(max(CombatRatingsAI.combine_ratings(enemy_rating, mob_rating), 0.98 * sys_status.get('fleetThreat', 0), 1.1 * lost_fleet_rating - monster_rating))
                sys_status['monsterThreat'] = int(max(monster_rating, 0.98 * sys_status.get('monsterThreat', 0), 1.1 * lost_fleet_rating - enemy_rating - mob_rating))
                sys_status['enemy_threat'] = int(max(enemy_rating, 0.98 * sys_status.get('enemy_threat', 0), 1.1 * lost_fleet_rating - monster_rating - mob_rating))
                sys_status['mydefenses'] = {'overall': 0, 'attack': 0, 'health': 0}
                sys_status['totalThreat'] = sys_status['fleetThreat']
                sys_status['regional_fleet_threats'] = sys_status['local_fleet_threats'].copy()
                continue

            # have either stale or current info
            pattack = 0
            phealth = 0
            mypattack, myphealth = 0, 0
            for pid in system.planetIDs:
                prating = self.assess_planet_threat(pid, sighting_age=current_turn - partial_vis_turn)
                planet = universe.getPlanet(pid)
                if not planet:
                    continue
                if planet.owner == self.empireID:  # TODO: check for diplomatic status
                    mypattack += prating['attack']
                    myphealth += prating['health']
                else:
                    if [special for special in planet.specials if "_NEST_" in special]:
                        sys_status['nest_threat'] = 100
                    pattack += prating['attack']
                    phealth += prating['health']
            sys_status['planetThreat'] = pattack * phealth
            sys_status['mydefenses'] = {'overall': mypattack * myphealth, 'attack': mypattack, 'health': myphealth}

            if max(sys_status.get('totalThreat', 0), pattack * phealth) >= 0.6 * lost_fleet_rating:  # previous threat assessment could account for losses, ignore the losses now
                lost_fleet_rating = 0

            # TODO use sitrep combat info rather than estimating stealthed enemies by fleets lost to them
            # TODO also only consider past stealthed fleet threat to still be present if the system is still obstructed
            # TODO: track visibility across turns in order to distinguish the blip of visibility in (losing) combat,
            # which FO currently treats as being for the previous turn, partially superseding the previous visibility for that turn
            if not partial_vis_turn == current_turn:  # (universe.getVisibility(sys_id, self.empire_id) >= fo.visibility.partial):
                sys_status.setdefault('local_fleet_threats', set())
                sys_status['currently_visible'] = False
                # print "Stale visibility for system %d ( %s ) -- last seen %d, current Turn %d -- basing threat assessment on old info and lost ships"%(sys_id, sys_status.get('name', "name unknown"), partial_vis_turn, currentTurn)
                sys_status['fleetThreat'] = int(max(CombatRatingsAI.combine_ratings(enemy_rating, mob_rating), 0.98 * sys_status.get('fleetThreat', 0), 2.0 * lost_fleet_rating - max(sys_status.get('monsterThreat', 0), monster_rating)))
                sys_status['enemy_threat'] = int(max(enemy_rating, 0.98 * sys_status.get('enemy_threat', 0), 1.1 * lost_fleet_rating - max(sys_status.get('monsterThreat', 0), monster_rating)))
                sys_status['monsterThreat'] = int(max(monster_rating, 0.98 * sys_status.get('monsterThreat', 0)))
                # sys_status['totalThreat'] = ((pattack + enemy_attack + monster_attack) ** 0.8) * ((phealth + enemy_health + monster_health)** 0.6)  # reevaluate this
                sys_status['totalThreat'] = max(CombatRatingsAI.combine_ratings_list([enemy_rating, mob_rating, monster_rating, pattack * phealth]), 2 * lost_fleet_rating, 0.98 * sys_status.get('totalThreat', 0))
            else:  # system considered visible #TODO: reevaluate as visibility rules change
                sys_status['currently_visible'] = True
                sys_status['local_fleet_threats'] = set(mobile_fleets)
                sys_status['fleetThreat'] = int(max(CombatRatingsAI.combine_ratings(enemy_rating, mob_rating), 2 * lost_fleet_rating - monster_rating))  # includes mobile monsters
                if verbose:
                    print "enemy threat calc parts: enemy rating %.1f, lost fleet rating %.1f, monster_rating %.1f" % (enemy_rating, lost_fleet_rating, monster_rating)
                sys_status['enemy_threat'] = int(max(enemy_rating, 2 * lost_fleet_rating - monster_rating))  # does NOT include mobile monsters
                sys_status['monsterThreat'] = monster_rating
                sys_status['totalThreat'] = CombatRatingsAI.combine_ratings_list([enemy_rating, mob_rating, monster_rating, pattack * phealth])
            sys_status['regional_fleet_threats'] = sys_status['local_fleet_threats'].copy()
            sys_status['fleetThreat'] = max(sys_status['fleetThreat'], sys_status.get('nest_threat', 0))
            sys_status['totalThreat'] = max(sys_status['totalThreat'], sys_status.get('nest_threat', 0))

            if partial_vis_turn > 0 and sys_id not in supply_unobstructed_systems:  # has been seen with Partial Vis, but is currently supply-blocked
                sys_status['fleetThreat'] = max(sys_status['fleetThreat'], min_hidden_attack * min_hidden_health)
                sys_status['totalThreat'] = max(sys_status['totalThreat'], ((pattack + min_hidden_attack) ** 0.8) * ((phealth + min_hidden_health) ** 0.6))
            if verbose and sys_status['fleetThreat'] > 0:
                print "%s intermediate status: %s" % (system, sys_status)

        enemy_supply, enemy_near_supply = self.assess_enemy_supply()  # TODO: assess change in enemy supply over time
        # assess secondary threats (threats of surrounding systems) and update my fleet rating
        for sys_id in system_id_list:
            sys_status = self.systemStatus[sys_id]
            sys_status['enemies_supplied'] = enemy_supply.get(sys_id, [])
            sys_status['enemies_nearly_supplied'] = enemy_near_supply.get(sys_id, [])
            my_ratings_list = []
            my_ratings_against_planets_list = []
            for fid in sys_status['myfleets']:
                this_rating = self.get_rating(fid, True, self.get_standard_enemy())
                my_ratings_list.append(this_rating)
                my_ratings_against_planets_list.append(self.get_rating(fid, against_planets=True))
            if sys_id != INVALID_ID:
                sys_status['myFleetRating'] = CombatRatingsAI.combine_ratings_list(my_ratings_list)
                sys_status['myFleetRatingVsPlanets'] = CombatRatingsAI.combine_ratings_list(my_ratings_against_planets_list)
                sys_status['all_local_defenses'] = CombatRatingsAI.combine_ratings(sys_status['myFleetRating'], sys_status['mydefenses']['overall'])
            sys_status['neighbors'] = set(dict_from_map(universe.getSystemNeighborsMap(sys_id, self.empireID)))
            
        for sys_id in system_id_list:
            sys_status = self.systemStatus[sys_id]
            neighbors = sys_status.get('neighbors', set())
            this_system = fo.getUniverse().getSystem(sys_id)
            if verbose:
                print "Regional Assessment for %s with local fleet threat %.1f" % (this_system, sys_status.get('fleetThreat', 0))
            jumps2 = set()
            jumps3 = set()
            jumps4 = set()
            for seta, setb in [(neighbors, jumps2), (jumps2, jumps3), (jumps3, jumps4)]:
                for sys2id in seta:
                    setb.update(self.systemStatus.get(sys2id, {}).get('neighbors', set()))
            jump2ring = jumps2 - neighbors - {sys_id}
            jump3ring = jumps3 - jumps2 - neighbors - {sys_id}
            jump4ring = jumps4 - jumps3  - jumps2 - neighbors - {sys_id}
            sys_status['2jump_ring'] = jump2ring
            sys_status['3jump_ring'] = jump3ring
            sys_status['4jump_ring'] = jump4ring
            threat, max_threat, myrating, j1_threats = self.area_ratings(neighbors, ref_sys_name="neighbors %s" % this_system) if verbose else self.area_ratings(neighbors)
            sys_status['neighborThreat'] = threat
            sys_status['max_neighbor_threat'] = max_threat
            sys_status['my_neighbor_rating'] = myrating
            threat, max_threat, myrating, j2_threats = self.area_ratings(jump2ring, ref_sys_name="jump2 %s" % this_system) if verbose else self.area_ratings(jump2ring)
            sys_status['jump2_threat'] = threat
            sys_status['my_jump2_rating'] = myrating
            threat, max_threat, myrating, j3_threats = self.area_ratings(jump3ring)
            sys_status['jump3_threat'] = threat
            sys_status['my_jump3_rating'] = myrating
            threat_keys = ['fleetThreat', 'neighborThreat', 'jump2_threat']  # for local system includes both enemies and mobs
            sys_status['regional_threat'] = CombatRatingsAI.combine_ratings_list(map(lambda x: sys_status.get(x, 0), threat_keys))
            # TODO: investigate cases where regional_threat has been nonzero but no regional_threat_fleets
            # (probably due to attenuating history of past threats)
            sys_status.setdefault('regional_fleet_threats', set()).update(j1_threats, j2_threats)
Ejemplo n.º 5
0
    def issue_fleet_orders(self):
        """issues AIFleetOrders which can be issued in system and moves to next one if is possible"""
        # TODO: priority
        order_completed = True
        print "--------------"
        print "Checking orders for fleet %d (on turn %d)" % (self.target_id, fo.currentTurn())
        print "\t Full Orders are:"
        for this_orders in self.orders:
            print "\t\t %s" % this_orders
        print "/t/t------"
        if AIFleetMissionType.FLEET_MISSION_INVASION in self.get_mission_types():
            self._check_retarget_invasion()
        for fleet_order in self.orders:
            print "  checking Order: %s" % fleet_order
            order_type = fleet_order.get_fleet_order_type()
            if order_type in [AIFleetOrderType.ORDER_COLONISE,
                              AIFleetOrderType.ORDER_OUTPOST,
                              AIFleetOrderType.ORDER_INVADE]:  # TODO: invasion?
                if self._check_abort_mission(fleet_order):
                    return
            self.check_mergers(context=str(fleet_order))
            if fleet_order.can_issue_order(verbose=True):
                if order_type == AIFleetOrderType.ORDER_MOVE and order_completed:  # only move if all other orders completed
                    fleet_order.issue_order()
                elif order_type not in [AIFleetOrderType.ORDER_MOVE, AIFleetOrderType.ORDER_DEFEND]:
                    fleet_order.issue_order()
                if not fleet_order.is_execution_completed():
                    order_completed = False
            else:  # check that we're not held up by a Big Monster
                if order_type == AIFleetOrderType.ORDER_MOVE:
                    this_system_id = fleet_order.get_target_target().target_id
                    this_status = foAI.foAIstate.systemStatus.setdefault(this_system_id, {})
                    if this_status.get('monsterThreat', 0) > fo.currentTurn() * ProductionAI.curBestMilShipRating()/4.0:
                        first_mission = self.get_mission_types()[0] if self.get_mission_types() else AIFleetMissionType.FLEET_MISSION_INVALID
                        if (first_mission not in (AIFleetMissionType.FLEET_MISSION_ATTACK,
                                                   AIFleetMissionType.FLEET_MISSION_MILITARY,
                                                   AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN,
                                                   AIFleetMissionType.FLEET_MISSION_SECURE,
                                                   ) or
                            fleet_order != self.orders[-1]  # if this move order is not this mil fleet's final destination, and blocked by Big Monster, release and hope for more effective reassignment
                            ):
                            print "Aborting mission due to being blocked by Big Monster at system %d, threat %d"%(this_system_id, foAI.foAIstate.systemStatus[this_system_id]['monsterThreat'])
                            print "Full set of orders were:"
                            for this_orders in self.orders:
                                print "\t\t %s" % this_orders
                            self.clear_fleet_orders()
                            self.clear_targets(([-1] + self.get_mission_types()[:1])[-1])
                            return
            # moving to another system stops issuing all orders in system where fleet is
            # move order is also the last order in system
            if order_type == AIFleetOrderType.ORDER_MOVE:
                fleet = fo.getUniverse().getFleet(self.target_id)
                if fleet.systemID != fleet_order.get_target_target().target_id:
                    break
        else:  # went through entire order list
            if order_completed:
                orders = self.orders
                last_order = orders[-1] if orders else None
                universe = fo.getUniverse()

                if last_order and last_order.get_fleet_order_type() == AIFleetOrderType.ORDER_COLONISE:
                    planet = universe.getPlanet(last_order.get_target_target().target_id)
                    sys_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, fo.empireID())).get(fo.visibility.partial, -9999)
                    planet_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.id, fo.empireID())).get(fo.visibility.partial, -9999)
                    if planet_partial_vis_turn == sys_partial_vis_turn and not planet.currentMeterValue(fo.meterType.population):
                        print "Potential Error: Fleet %d has tentatively completed its colonize mission but will wait to confirm population." % self.target_id
                        print "    Order details are %s" % last_order
                        print "    Order is valid: %s ; is Executed : %s; is execution completed: %s " % (last_order.is_valid(), last_order.isExecuted(), last_order.isExecutionCompleted())
                        if not last_order.is_valid():
                            source_target = last_order.get_source_target()
                            target_target = last_order.get_target_target()
                            print "        source target validity: %s; target target validity: %s " % (source_target.valid, target_target.valid)
                            if EnumsAI.AITargetType.TARGET_SHIP == source_target.target_type:
                                ship_id = source_target.target_id
                                ship = universe.getShip(ship_id)
                                if not ship:
                                    print "Ship id %d not a valid ship id" % ship_id
                                print "        source target Ship (%d), species %s, can%s colonize" % (ship_id, ship.speciesName, ["not", ""][ship.canColonize])
                        return  # colonize order must not have completed yet
                clearAll = True
                last_sys_target = -1
                if last_order and last_order.get_fleet_order_type() == AIFleetOrderType.ORDER_MILITARY:
                    last_sys_target = last_order.get_target_target().target_id
                    # if (AIFleetMissionType.FLEET_MISSION_SECURE in self.get_mission_types()) or # not doing this until decide a way to release from a SECURE mission
                    secure_targets = set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs + AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs)
                    if last_sys_target in secure_targets:  # consider a secure mission
                        if last_sys_target in AIstate.colonyTargetedSystemIDs:
                            secure_type = "Colony"
                        elif last_sys_target in AIstate.outpostTargetedSystemIDs:
                            secure_type = "Outpost"
                        elif last_sys_target in AIstate.invasionTargetedSystemIDs:
                            secure_type = "Invasion"
                        elif last_sys_target in AIstate.blockadeTargetedSystemIDs:
                            secure_type = "Blockade"
                        else:
                            secure_type = "Unidentified"
                        print "Fleet %d has completed initial stage of its mission to secure system %d (targeted for %s), may release a portion of ships" % (self.target_id, last_sys_target, secure_type)
                        clearAll = False
                fleet_id = self.target_id
                if clearAll:
                    if orders:
                        print "Fleet %d has completed its mission; clearing all orders and targets." % self.target_id
                        print "Full set of orders were:"
                        for this_orders in orders:
                            print "\t\t %s" % this_orders
                        self.clear_fleet_orders()
                        self.clear_targets(([-1] + self.get_mission_types()[:1])[-1])
                        if foAI.foAIstate.get_fleet_role(fleet_id) in (AIFleetMissionType.FLEET_MISSION_MILITARY,
                                                                       AIFleetMissionType.FLEET_MISSION_ATTACK,
                                                                       AIFleetMissionType.FLEET_MISSION_DEFEND,
                                                                       AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN,
                                                                       AIFleetMissionType.FLEET_MISSION_SECURE):
                            allocations = MilitaryAI.get_military_fleets(milFleetIDs=[fleet_id], tryReset=False, thisround="Fleet %d Reassignment" % fleet_id)
                            if allocations:
                                MilitaryAI.assign_military_fleets_to_systems(useFleetIDList=[fleet_id], allocations=allocations)
                    else:  # no orders
                        print "No Current Orders"
                else:
                    #TODO: evaluate releasing a smaller portion or none of the ships
                    system_status = foAI.foAIstate.systemStatus.setdefault(last_sys_target, {})
                    new_fleets = []
                    threat_present = (system_status.get('totalThreat', 0) != 0) or (system_status.get('neighborThreat', 0) != 0)
                    target_system = universe.getSystem(last_sys_target)
                    if not threat_present and target_system:
                        for pid in target_system.planetIDs:
                            planet = universe.getPlanet(pid)
                            if planet and planet.owner != fo.empireID() and planet.currentMeterValue(fo.meterType.maxDefense) > 0:
                                threat_present = True
                                break
                    if not threat_present:
                        print "No current threat in target system; releasing a portion of ships."
                        new_fleets = FleetUtilsAI.split_fleet(self.target_id)  # at least first stage of current task is done; release extra ships for potential other deployments
                    else:
                        print "Threat remains in target system; NOT releasing any ships."
                    new_military_fleets = []
                    for fleet_id in new_fleets:
                        if foAI.foAIstate.get_fleet_role(fleet_id) in (AIFleetMissionType.FLEET_MISSION_MILITARY,
                                                                       AIFleetMissionType.FLEET_MISSION_ATTACK,
                                                                       AIFleetMissionType.FLEET_MISSION_DEFEND,
                                                                       AIFleetMissionType.FLEET_MISSION_HIT_AND_RUN,
                                                                       AIFleetMissionType.FLEET_MISSION_SECURE):
                            new_military_fleets.append(fleet_id)
                    allocations = []
                    if new_military_fleets:
                        allocations = MilitaryAI.get_military_fleets(milFleetIDs=new_military_fleets, tryReset=False, thisround="Fleet Reassignment %s" % new_military_fleets)
                    if allocations:
                        MilitaryAI.assign_military_fleets_to_systems(useFleetIDList=new_military_fleets, allocations=allocations)
def int_int_map_to_string(int_int_map):
    return str(dict_from_map(int_int_map))
 def wrapper(*args):
     return dict_from_map(method(*args))
Ejemplo n.º 8
0
def evaluate_invasion_planet(planetID, missionType, fleetSupplyablePlanetIDs, empire, secureAIFleetMissions, verbose=True):
    """return the invasion value (score, troops) of a planet"""
    detail = []
    buildingValues = {"BLD_IMPERIAL_PALACE": 1000,
                                            "BLD_CULTURE_ARCHIVES": 1000,
                                            "BLD_SHIPYARD_BASE": 100,
                                            "BLD_SHIPYARD_ORG_ORB_INC": 200,
                                            "BLD_SHIPYARD_ORG_XENO_FAC": 200,
                                            "BLD_SHIPYARD_ORG_CELL_GRO_CHAMB": 200,
                                            "BLD_SHIPYARD_CON_NANOROBO": 300,
                                            "BLD_SHIPYARD_CON_GEOINT": 400,
                                            "BLD_SHIPYARD_CON_ADV_ENGINE": 1000,
                                            "BLD_SHIPYARD_AST": 300,
                                            "BLD_SHIPYARD_AST_REF": 1000,
                                            "BLD_SHIPYARD_ENRG_SOLAR": 1500,
                                            "BLD_INDUSTRY_CENTER": 500,
                                            "BLD_GAS_GIANT_GEN": 200,
                                            "BLD_SOL_ORB_GEN": 800,
                                            "BLD_BLACK_HOLE_POW_GEN": 2000,
                                            "BLD_ENCLAVE_VOID": 500,
                                            "BLD_NEUTRONIUM_EXTRACTOR": 2000,
                                            "BLD_NEUTRONIUM_SYNTH": 2000,
                                            "BLD_NEUTRONIUM_FORGE": 1000,
                                            "BLD_CONC_CAMP": 100,
                                            "BLD_BIOTERROR_PROJECTOR": 1000,
                                            "BLD_SHIPYARD_ENRG_COMP": 3000,
                                            }
    #TODO: add more factors, as used for colonization
    universe = fo.getUniverse()
    empireID = empire.empireID
    maxJumps=8
    planet = universe.getPlanet(planetID)
    if planet is None:  #TODO: exclude planets with stealth higher than empireDetection
        print "invasion AI couldn't access any info for planet id %d"%planetID
        return [0, 0]

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

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

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

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

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

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

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

    pmaxShield = planet.currentMeterValue(fo.meterType.maxShield)
    if verbose:
        print "invasion eval of %s %d --- maxShields %.1f -- sysFleetThreat %.1f -- sysMonsterThreat %.1f"%(planet.name, planetID, pmaxShield, sysFThrt, sysMThrt)
    supplyVal=0
    enemyVal=0
    if planet.owner!=-1 : #value in taking this away from an enemy
        enemyVal= 20* (planet.currentMeterValue(fo.meterType.targetIndustry) + 2*planet.currentMeterValue(fo.meterType.targetResearch))
    if pSysID in ColonisationAI.annexableSystemIDs: #TODO: extend to rings
        supplyVal = 100
    elif pSysID in ColonisationAI.annexableRing1:
        supplyVal = 200
    elif pSysID in ColonisationAI.annexableRing2:
        supplyVal = 300
    elif pSysID in ColonisationAI.annexableRing3:
        supplyVal = 400
    if max_path_threat > 0.5 * mil_ship_rating:
        if max_path_threat < 3 * mil_ship_rating:
            supplyVal *= 0.5
        else:
            supplyVal *= 0.2
        
    threatFactor = min(1, 0.2*MilitaryAI.totMilRating/(sysTotThrt+0.001))**2  #devalue invasions that would require too much military force
    buildTime=4
    if system_secured:
        plannedTroops = troops
    else:
        plannedTroops = min(troops+maxJumps+buildTime, maxTroops)
    if not tech_is_complete("SHP_ORG_HULL"):
        troopCost = math.ceil(plannedTroops/6.0) * (40*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP))
    else:
        troopCost = math.ceil(plannedTroops/6.0) * (20*(1+foAI.foAIstate.shipCount * AIDependencies.SHIP_UPKEEP))
    planet_score = retaliation_risk_factor(planet.owner) * threatFactor * max(0, popVal+supplyVal+bldTally+enemyVal-0.8*troopCost)
    if clear_path:
        planet_score *= 1.5
    invscore = [ planet_score, plannedTroops ]
    print invscore, "projected Troop Cost:", troopCost, ", threatFactor: ", threatFactor, ", planet detail ", detail, "popval, supplyval, bldval, enemyval", popVal, supplyVal, bldTally, enemyVal
    return invscore
Ejemplo n.º 9
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = foAI.foAIstate.empireID
    exploration_list = [start_system_id]
    while exploration_list:
        cur_system_id = exploration_list.pop()
        if cur_system_id in graphFlags:
            continue
        graphFlags[cur_system_id] = 1
        system = universe.getSystem(cur_system_id)
        if not system:
            sys_name = foAI.foAIstate.systemStatus.get(cur_system_id, {}).get(
                'name', "name unknown")
        else:
            sys_name = system.name or foAI.foAIstate.systemStatus.get(
                cur_system_id, {}).get('name', "name unknown")
        if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in foAI.foAIstate.visInteriorSystemIDs:
            pre_vis = "an interior system"
        else:
            pre_vis = "an unknown 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 = [
                '%s: %s' % (vis.name, turn)
                for vis, turn in visibility_turn_list
            ]
            print "*** system ID %d ( %s ) ; previously %s, new visibility turns info: %s " % (
                cur_system_id, sys_name, pre_vis, visibility_info)
        status_str = "*** system ID %d ( %s ) ; " % (cur_system_id, sys_name)
        has_been_visible = universe.getVisibilityTurnsMap(
            cur_system_id, empire_id).get(fo.visibility.partial, 0) > 0
        is_connected = universe.systemsConnected(cur_system_id, home_system_id,
                                                 -1)  # self.empire_id)
        status_str += " -- is %s partially visible " % (["not", ""
                                                         ][has_been_visible])
        status_str += " -- is %s visibly connected to homesystem " % (
            ["not", ""][is_connected])
        if has_been_visible:
            sys_status = foAI.foAIstate.systemStatus.setdefault(
                cur_system_id, {})
            foAI.foAIstate.visInteriorSystemIDs[cur_system_id] = 1
            if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
                del foAI.foAIstate.visBorderSystemIDs[cur_system_id]
            #neighbors= dict( [(el.key(), el.data()) for el in universe.getSystemNeighborsMap(cur_system_id, empire_id)] )  #
            neighbors = set(
                dict_from_map(
                    universe.getSystemNeighborsMap(cur_system_id,
                                                   empire_id)).keys())
            sys_status.setdefault('neighbors', set()).update(neighbors)
            sys_planets = sys_status.setdefault('planets', {})
            if fo.currentTurn() < 50:
                print "    previously knew of system %d planets %s" % (
                    cur_system_id, sys_planets.keys())
            if system:
                for planet_id in system.planetIDs:
                    sys_planets.setdefault(planet_id,
                                           {}).setdefault(TARGET_POP, 0)
                    sys_planets[planet_id].setdefault(TROOPS, 0)
                    planet = universe.getPlanet(planet_id)

                    if planet:
                        new_pop = planet.currentMeterValue(
                            fo.meterType.targetPopulation)
                        if new_pop != sys_planets[planet_id][TARGET_POP]:
                            if fo.currentTurn() < 50:
                                print "  * updating targetPop of planet %d ( %s ) to %.2f from %.2f" % (
                                    planet_id, planet.name, new_pop,
                                    sys_planets[planet_id][TARGET_POP])
                        troops = planet.currentMeterValue(fo.meterType.troops)
                        if troops != sys_planets[planet_id].get(TROOPS, 0):
                            if fo.currentTurn() < 50:
                                print "  * updating troops of planet %d ( %s ) to %.2f from %.2f" % (
                                    planet_id, planet.name, troops,
                                    sys_planets[planet_id][TROOPS])
                        sys_planets[planet_id][TARGET_POP] = new_pop
                        sys_planets[planet_id][TROOPS] = troops
            if fo.currentTurn() < 50:
                print "    now know of system %d planets %s" % (
                    cur_system_id, sys_planets.keys())
            #neighbors = list( universe.getImmediateNeighbors(cur_system_id, empire_id) )  #imNeighbors
            #if set(neighbors) != set(neighbors2):
            # print "Error with neighbors: imn giving %s ; giN giving %s"%(neighbors2, neighbors)
            if neighbors:
                status_str += " -- has neighbors %s " % neighbors
                for sys_id in neighbors:
                    if sys_id not in foAI.foAIstate.exploredSystemIDs:
                        foAI.foAIstate.unexploredSystemIDs[sys_id] = 1
                    if (sys_id not in graphFlags) and (
                            sys_id not in foAI.foAIstate.visInteriorSystemIDs):
                        foAI.foAIstate.visBorderSystemIDs[sys_id] = 1
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            print status_str
            print "----------------------------------------------------------"
Ejemplo n.º 10
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = foAI.foAIstate.empireID
    exploration_list = [start_system_id]
    while exploration_list:
        cur_system_id = exploration_list.pop()
        if cur_system_id in graphFlags:
            continue
        graphFlags[cur_system_id] = 1
        system = universe.getSystem(cur_system_id)
        if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in foAI.foAIstate.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)
            print "%s previously %s, new visibility turns info: %s " % (
                system_header, pre_vis, visibility_info)
            status_info = []
        else:
            status_info = [system_header]

        has_been_visible = universe.getVisibilityTurnsMap(
            cur_system_id, empire_id).get(fo.visibility.partial, 0) > 0
        is_connected = universe.systemsConnected(cur_system_id, home_system_id,
                                                 -1)  # self.empire_id)
        status_info.append("    -- is%s partially visible" %
                           ([" not", ""][has_been_visible]))
        status_info.append("    -- is%s visibly connected to homesystem" %
                           ([" not", ""][is_connected]))
        if has_been_visible:
            sys_status = foAI.foAIstate.systemStatus.setdefault(
                cur_system_id, {})
            foAI.foAIstate.visInteriorSystemIDs[cur_system_id] = 1
            if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
                del foAI.foAIstate.visBorderSystemIDs[cur_system_id]
            neighbors = set(
                dict_from_map(
                    universe.getSystemNeighborsMap(cur_system_id,
                                                   empire_id)).keys())
            sys_status.setdefault('neighbors', set()).update(neighbors)
            sys_planets = sys_status.setdefault('planets', {})
            if fo.currentTurn() < 50:
                print "    previously knew planets: %s" % sys_planets.keys()
            if system:
                for planet_id in system.planetIDs:
                    sys_planets.setdefault(planet_id,
                                           {}).setdefault(TARGET_POP, 0)
                    sys_planets[planet_id].setdefault(TROOPS, 0)
                    planet = universe.getPlanet(planet_id)

                    if planet:
                        new_pop = planet.currentMeterValue(
                            fo.meterType.targetPopulation)
                        if new_pop != sys_planets[planet_id][TARGET_POP]:
                            if fo.currentTurn() < 50:
                                print "  * updating targetPop of planet %s to %.2f from %.2f" % (
                                    planet, new_pop,
                                    sys_planets[planet_id][TARGET_POP])
                        troops = planet.currentMeterValue(fo.meterType.troops)
                        if troops != sys_planets[planet_id].get(TROOPS, 0):
                            if fo.currentTurn() < 50:
                                print "  * updating troops of planet %s to %.2f from %.2f" % (
                                    planet, troops,
                                    sys_planets[planet_id][TROOPS])
                        sys_planets[planet_id][TARGET_POP] = new_pop
                        sys_planets[planet_id][TROOPS] = troops
            if fo.currentTurn() < 50:
                print "    known planets %s" % sys_planets.keys()
            if neighbors:
                status_info.append(" -- has neighbors %s" % sorted(neighbors))
                for sys_id in neighbors:
                    if sys_id not in foAI.foAIstate.exploredSystemIDs:
                        foAI.foAIstate.unexploredSystemIDs[sys_id] = 1
                    if (sys_id not in graphFlags) and (
                            sys_id not in foAI.foAIstate.visInteriorSystemIDs):
                        foAI.foAIstate.visBorderSystemIDs[sys_id] = 1
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            print '\n'.join(status_info)
            print "----------------------------------------------------------"
Ejemplo n.º 11
0
def get_invasion_fleets():
    """get invasion fleets"""
    invasion_timer.start("gathering initial info")

    all_invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    AIstate.invasionFleetIDs = FleetUtilsAI.extract_fleet_ids_without_mission_types(all_invasion_fleet_ids)

    # get supplyable planets
    universe = fo.getUniverse()
    empire = fo.getEmpire()
    empire_id = empire.empireID
    capital_id = PlanetUtilsAI.get_capital()
    homeworld=None
    if capital_id:
        homeworld = universe.getPlanet(capital_id)
    if homeworld:
        home_system_id = homeworld.systemID
    else:
        home_system_id = -1

    fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
    fleet_supplyable_planet_ids = PlanetUtilsAI.get_planets_in__systems_ids(fleet_supplyable_system_ids)

    prime_invadable_system_ids = set(ColonisationAI.annexableSystemIDs)
    prime_invadable_planet_ids = PlanetUtilsAI.get_planets_in__systems_ids(prime_invadable_system_ids)

    visible_system_ids = foAI.foAIstate.visInteriorSystemIDs.keys() + foAI.foAIstate. visBorderSystemIDs.keys()

    if home_system_id != -1:
        accessible_system_ids = [sys_id for sys_id in visible_system_ids if (sys_id != -1 ) and universe.systemsConnected(sys_id, home_system_id, empire_id) ]
    else:
        print "Invasion Warning: this empire has no identifiable homeworld, will therefor treat all visible planets as accessible."
        accessible_system_ids = visible_system_ids #TODO: check if any troop ships still owned, use their system as home system
    acessible_planet_ids = PlanetUtilsAI.get_planets_in__systems_ids(accessible_system_ids)
    print "Accessible Systems: ", ", ".join(PlanetUtilsAI.sys_name_ids(accessible_system_ids))
    print

    #all_owned_planet_ids = PlanetUtilsAI.get_all_owned_planet_ids(exploredPlanetIDs)
    all_owned_planet_ids = PlanetUtilsAI.get_all_owned_planet_ids(acessible_planet_ids)#need these for unpopulated outposts
    # print "All Owned and Populated PlanetIDs: " + str(all_owned_planet_ids)

    all_populated_planets = PlanetUtilsAI.get_populated_planet_ids(acessible_planet_ids)#need this for natives
    print "All Visible and accessible Populated PlanetIDs (including this empire's): ", ", ".join(PlanetUtilsAI.planet_name_ids(all_populated_planets ))
    print
    print "Prime Invadable Target Systems: ", ", ".join(PlanetUtilsAI.sys_name_ids(prime_invadable_system_ids))
    print

    empire_owned_planet_ids = PlanetUtilsAI.get_owned_planets_by_empire(universe.planetIDs)
    # print "Empire Owned PlanetIDs: " + str(empire_owned_planet_ids)

    invadable_planet_ids = set(prime_invadable_planet_ids).intersection(set(all_owned_planet_ids).union(all_populated_planets ) - set(empire_owned_planet_ids))
    print "Prime Invadable PlanetIDs: ", ", ".join(PlanetUtilsAI.planet_name_ids(invadable_planet_ids))

    print
    print "Current Invasion Targeted SystemIDs: ", ", ".join(PlanetUtilsAI.sys_name_ids(AIstate.invasionTargetedSystemIDs))
    invasion_targeted_planet_ids = get_invasion_targeted_planet_ids(universe.planetIDs, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, empire_id)
    invasion_targeted_planet_ids.extend( get_invasion_targeted_planet_ids(universe.planetIDs, EnumsAI.AIFleetMissionType.FLEET_MISSION_ORBITAL_INVASION, empire_id))
    all_invasion_targeted_system_ids = set(PlanetUtilsAI.get_systems(invasion_targeted_planet_ids))

    print "Current Invasion Targeted PlanetIDs: ", ", ".join(PlanetUtilsAI.planet_name_ids(invasion_targeted_planet_ids))

    invasion_fleet_ids = FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION)
    if not invasion_fleet_ids:
        print "Available Invasion Fleets: 0"
    else:
        print "Invasion FleetIDs: " + str(FleetUtilsAI.get_empire_fleet_ids_by_role(EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION))

    num_invasion_fleets = len(FleetUtilsAI.extract_fleet_ids_without_mission_types(invasion_fleet_ids))
    print "Invasion Fleets Without Missions:    " + str(num_invasion_fleets)
    
    invasion_timer.start("planning troop base production")
    # only do base invasions if aggression is typical or above
    reserved_troop_base_targets = []
    if foAI.foAIstate.aggression > fo.aggression.typical:
        available_pp = {}
        for el in  empire.planetsWithAvailablePP:  #keys are sets of ints; data is doubles
            avail_pp = el.data()
            for pid in el.key():
                available_pp[pid] = avail_pp
        if len (invadable_planet_ids) > 0:
            #print "Evaluating Troop Bases (SpaceInvaders) for %s"%(invadable_planet_ids)
            pass
        for pid in invadable_planet_ids: #TODO: reorganize
            planet = universe.getPlanet(pid)
            if not planet: 
                continue
            sys_id = planet.systemID
            sys_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, empire_id)).get(fo.visibility.partial, -9999)
            planet_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(pid, empire_id)).get(fo.visibility.partial, -9999)
            if planet_partial_vis_turn < sys_partial_vis_turn:
                #print "rejecting %s due to stealth"%planet.name
                continue
            for pid2 in ColonisationAI.empireSpeciesSystems.get(sys_id,  {}).get('pids', []):
                if available_pp.get(pid2,  0) < 2: #TODO: improve troop base PP sufficiency determination
                    #print "rejecting %s due to insufficient avail PP"%planet.name
                    break
                planet2 = universe.getPlanet(pid2)
                if not planet2: 
                    continue
                if (pid not in  foAI.foAIstate.qualifyingTroopBaseTargets) and (planet2.speciesName  in ColonisationAI.empireShipBuilders):
                    #print "Adding %s to Troop Bases (SpaceInvaders) potential target list, from %s"%(planet.name, planet2.name) 
                    foAI.foAIstate.qualifyingTroopBaseTargets.setdefault(pid,  [pid2,  -1])
                    break

        for pid in list(foAI.foAIstate.qualifyingTroopBaseTargets):
            planet = universe.getPlanet(pid) #TODO: also check that still have a colony in this system that can make troops
            if planet and planet.owner == empire_id:
                del foAI.foAIstate.qualifyingTroopBaseTargets[pid]

        secureAIFleetMissions = foAI.foAIstate.get_fleet_missions_with_any_mission_types([EnumsAI.AIFleetMissionType.FLEET_MISSION_SECURE])
        #print "considering possible troop bases at %s" % (foAI.foAIstate.qualifyingTroopBaseTargets.keys())
        for pid in (set(foAI.foAIstate.qualifyingTroopBaseTargets.keys()) - set(invasion_targeted_planet_ids)): #TODO: consider overriding standard invasion mission
            planet = universe.getPlanet(pid)
            if  foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] != -1: 
                reserved_troop_base_targets.append(pid)
                if planet:
                    all_invasion_targeted_system_ids.add( planet.systemID )
                continue  #already building for here
            sys_id = planet.systemID
            this_sys_status = foAI.foAIstate.systemStatus.get( sys_id,  {} )
            if  ((planet.currentMeterValue(fo.meterType.shield) > 0) and 
                        (this_sys_status.get('myFleetRating', 0) < (0.8 * this_sys_status.get('totalThreat', 0)))):
                continue
            loc = foAI.foAIstate.qualifyingTroopBaseTargets[pid][0]
            this_score,  p_troops = evaluate_invasion_planet(pid, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, fleet_supplyable_planet_ids, empire,  secureAIFleetMissions,  False)
            bestShip,  colDesign,  buildChoices = ProductionAI.getBestShipInfo(EnumsAI.AIPriorityType.PRIORITY_PRODUCTION_ORBITAL_INVASION,  loc)
            if not bestShip:
                #print "Error: no troop base can be built at ",  PlanetUtilsAI.planet_name_ids([loc])
                continue
            #print "selecting  ",  PlanetUtilsAI.planet_name_ids([loc]),  " to build Orbital troop bases"
            n_bases = math.ceil((p_troops+1) / 2)#TODO: reconsider this +1 safety factor
            retval  = fo.issueEnqueueShipProductionOrder(bestShip, loc)
            print "Enqueueing %d Troop Bases at %s for %s"%( n_bases,  PlanetUtilsAI.planet_name_ids([loc]),  PlanetUtilsAI.planet_name_ids([pid]))
            if retval !=0:
                all_invasion_targeted_system_ids.add( planet.systemID )
                reserved_troop_base_targets.append(pid)
                foAI.foAIstate.qualifyingTroopBaseTargets[pid][1] = loc
                fo.issueChangeProductionQuantityOrder(empire.productionQueue.size -1,  1,  int(n_bases))
                res=fo.issueRequeueProductionOrder(empire.productionQueue.size -1,  0)

    invasion_timer.start("evaluating target planets")
    #TODO: check if any invasion_targeted_planet_ids need more troops assigned
    evaluatedPlanetIDs = list(set(invadable_planet_ids) - set(invasion_targeted_planet_ids) - set(reserved_troop_base_targets) )
    print "Evaluating potential invasions, PlanetIDs: " + str(evaluatedPlanetIDs)

    evaluatedPlanets = assign_invasion_values(evaluatedPlanetIDs, EnumsAI.AIFleetMissionType.FLEET_MISSION_INVASION, fleet_supplyable_planet_ids, empire)

    sortedPlanets = [(pid, pscore, ptroops) for (pid, (pscore, ptroops)) in evaluatedPlanets.items() ]
    sortedPlanets.sort(lambda x, y: cmp(x[1], y[1]), reverse=True)
    sortedPlanets = [(pid, pscore%10000, ptroops) for (pid, pscore, ptroops) in sortedPlanets ]

    print
    if sortedPlanets:
        print "Invadable planets\nIDs, ID | Score | Name | Race | Troops"
        for pid, pscore, ptroops in sortedPlanets:
            planet = universe.getPlanet(pid)
            if planet:
                print "%6d | %6d | %16s | %16s | %d"%(pid, pscore, planet.name, planet.speciesName, ptroops)
            else:
                print "%6d | %6d | Error: invalid planet ID"%(pid, pscore)
    else:
        print "No Invadable planets identified"

    sortedPlanets = [(pid, pscore, ptroops) for (pid, pscore, ptroops) in sortedPlanets if pscore > 0]
    # export opponent planets for other AI modules
    AIstate.opponentPlanetIDs = [pid for pid, pscore, trp in sortedPlanets]
    AIstate.invasionTargets = sortedPlanets

    # export invasion targeted systems for other AI modules
    AIstate.invasionTargetedSystemIDs = list(all_invasion_targeted_system_ids)
    invasion_timer.stop(section_name="evaluating %d target planets" % (len(evaluatedPlanetIDs)))
    invasion_timer.end()
Ejemplo n.º 12
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = foAI.foAIstate.empireID
    exploration_list = [start_system_id]
    while exploration_list:
        cur_system_id = exploration_list.pop()
        if cur_system_id in graphFlags:
            continue
        graphFlags[cur_system_id] = 1
        system = universe.getSystem(cur_system_id)
        if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in foAI.foAIstate.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)
            print "%s previously %s. Visibility per turn: %s " % (system_header, pre_vis, visibility_info)
            status_info = []
        else:
            status_info = [system_header]

        has_been_visible = universe.getVisibilityTurnsMap(cur_system_id, empire_id).get(fo.visibility.partial, 0) > 0
        is_connected = universe.systemsConnected(cur_system_id, home_system_id, -1)  # self.empire_id)
        status_info.append("    -- is%s partially visible" % ([" not", ""][has_been_visible]))
        status_info.append("    -- is%s visibly connected to homesystem" % ([" not", ""][is_connected]))
        if has_been_visible:
            sys_status = foAI.foAIstate.systemStatus.setdefault(cur_system_id, {})
            foAI.foAIstate.visInteriorSystemIDs[cur_system_id] = 1
            if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
                del foAI.foAIstate.visBorderSystemIDs[cur_system_id]
            neighbors = set(dict_from_map(universe.getSystemNeighborsMap(cur_system_id, empire_id)).keys())
            sys_status.setdefault('neighbors', set()).update(neighbors)
            sys_planets = sys_status.setdefault('planets', {})
            if fo.currentTurn() < 50:
                print "    previously known planets: %s" % sys_planets.keys()
            if system:
                for planet_id in system.planetIDs:
                    sys_planets.setdefault(planet_id, {}).setdefault(TARGET_POP, 0)
                    sys_planets[planet_id].setdefault(TROOPS, 0)
                    planet = universe.getPlanet(planet_id)

                    if planet:
                        new_pop = planet.currentMeterValue(fo.meterType.targetPopulation)
                        if new_pop != sys_planets[planet_id][TARGET_POP]:
                            if fo.currentTurn() < 50:
                                print "  * updating targetPop of planet %s to %.2f from %.2f" % (planet, new_pop, sys_planets[planet_id][TARGET_POP])
                        troops = planet.currentMeterValue(fo.meterType.troops)
                        if troops != sys_planets[planet_id].get(TROOPS, 0):
                            if fo.currentTurn() < 50:
                                print "  * updating troops of planet %s to %.2f from %.2f" % (planet, troops, sys_planets[planet_id][
                                    TROOPS])
                        sys_planets[planet_id][TARGET_POP] = new_pop
                        sys_planets[planet_id][TROOPS] = troops
            if fo.currentTurn() < 50:
                print "    known planets %s" % sys_planets.keys()
            if neighbors:
                status_info.append(" -- has neighbors %s" % sorted(neighbors))
                for sys_id in neighbors:
                    if sys_id not in foAI.foAIstate.exploredSystemIDs:
                        foAI.foAIstate.unexploredSystemIDs[sys_id] = 1
                    if (sys_id not in graphFlags) and (sys_id not in foAI.foAIstate.visInteriorSystemIDs):
                        foAI.foAIstate.visBorderSystemIDs[sys_id] = 1
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            print '\n'.join(status_info)
            print "----------------------------------------------------------"
Ejemplo n.º 13
0
    def is_valid(self, verbose = True):
        """Check if FleetOrder could be somehow in future issued = is valid."""
        if self.executed and self.execution_completed:
            if verbose:
                print "\t\t order not valid because already executed and completed"
            return False
        if self.fleet.valid and self.target.valid:
            universe = fo.getUniverse()
            target_type = self.target.target_type
            fleet_id = self.fleet.target_id
            # outpost
            if AIFleetOrderType.ORDER_OUTPOST == self.order_type:
                # colonise planet
                if TargetType.TARGET_PLANET == target_type:
                    planet = universe.getPlanet(self.target.target_id)
                    sys_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, fo.empireID())).get(fo.visibility.partial, -9999)
                    planet_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.id, fo.empireID())).get(fo.visibility.partial, -9999)
                    if not (planet_partial_vis_turn == sys_partial_vis_turn and planet.unowned):
                        self.executed = True
                        self.execution_completed = True
                        return False
                    else:
                        fleet = universe.getFleet(fleet_id)
                        return fleet.hasOutpostShips
                else:
                    return False
            # colonise
            elif AIFleetOrderType.ORDER_COLONISE == self.order_type:

                # colonise planet
                if TargetType.TARGET_PLANET == target_type:
                    planet = universe.getPlanet(self.target.target_id)
                    sys_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, fo.empireID())).get(fo.visibility.partial, -9999)
                    planet_partial_vis_turn = dict_from_map(universe.getVisibilityTurnsMap(planet.id, fo.empireID())).get(fo.visibility.partial, -9999)
                    if not (planet_partial_vis_turn == sys_partial_vis_turn and planet.unowned or (planet.ownedBy(fo.empireID()) and not planet.currentMeterValue(fo.meterType.population))):
                        self.executed = True
                        self.execution_completed = True
                        return False
                    else:
                        fleet = universe.getFleet(fleet_id)
                        return fleet.hasColonyShips
                else:
                    return False
            # invade
            elif AIFleetOrderType.ORDER_INVADE == self.order_type:
                # invade planet
                if TargetType.TARGET_PLANET == target_type:
                    planet = universe.getPlanet(self.target.target_id)
                    planet_population = planet.currentMeterValue(fo.meterType.population)
                    if planet.unowned and not planet_population:
                        print "\t\t invasion order not valid due to target planet status-- owned: %s and population %.1f" % (not planet.unowned, planet_population)
                        self.executed = True
                        self.execution_completed = True
                        return False
                    else:
                        fleet = universe.getFleet(fleet_id)
                        return fleet.hasTroopShips
                else:
                    return False
            # military
            elif AIFleetOrderType.ORDER_MILITARY == self.order_type:
                fleet = universe.getFleet(fleet_id)
                return fleet.hasArmedShips and TargetType.TARGET_SYSTEM == target_type
            # move to system
            elif AIFleetOrderType.ORDER_MOVE == self.order_type:
                return TargetType.TARGET_SYSTEM == target_type
            # resupply
            elif AIFleetOrderType.ORDER_RESUPPLY == self.order_type:
                # move to system
                if TargetType.TARGET_SYSTEM == target_type:
                    empire = fo.getEmpire()
                    return self.target.target_id in empire.fleetSupplyableSystemIDs
                else:
                    return False
            # repair
            elif AIFleetOrderType.ORDER_REPAIR == self.order_type:
                # move to system
                if TargetType.TARGET_SYSTEM == target_type:
                    empire = fo.getEmpire()
                    return self.target.target_id in empire.fleetSupplyableSystemIDs  # TODO: check for drydock still there/owned
                else:
                    return False
            # split fleet
            elif AIFleetOrderType.ORDER_SPLIT_FLEET == self.order_type:
                return TargetType.TARGET_SHIP == target_type and self.ship_in_fleet()
            elif AIFleetOrderType.ORDER_ATTACK == self.order_type:
                return target_type in (TargetType.TARGET_SYSTEM, TargetType.TARGET_PLANET)
            elif AIFleetOrderType.ORDER_DEFEND == self.order_type:
                return target_type in (TargetType.TARGET_SYSTEM, TargetType.TARGET_PLANET)
        else:
            if verbose:
                print "\t\t order not valid: fleet validity: %s and target validity %s" % (self.fleet.valid, self.target.valid)
        return False
Ejemplo n.º 14
0
    def __update_system_status(self):
        print 10 * "=", "Updating System Threats", 10 * "="
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_id = fo.empireID()
        destroyed_object_ids = universe.destroyedObjectIDs(empire_id)
        supply_unobstructed_systems = set(empire.supplyUnobstructedSystems)
        min_hidden_attack = 4
        min_hidden_health = 8

        # TODO: Variables that are recalculated each turn from scratch should not be stored in AIstate
        # clear previous game state
        for sys_id in self.systemStatus:
            self.systemStatus[sys_id]['enemy_ship_count'] = 0
            self.systemStatus[sys_id]['myFleetRating'] = 0
            self.systemStatus[sys_id]['myFleetRatingVsPlanets'] = 0

        # for use in debugging
        verbose = False

        # assess enemy fleets that may have been momentarily visible
        enemies_by_system = {}
        my_fleets_by_system = {}
        fleet_spot_position = {}
        current_turn = fo.currentTurn()
        for fleet_id in universe.fleetIDs:
            fleet = universe.getFleet(fleet_id)
            if not fleet or fleet.empty:
                self.delete_fleet_info(fleet_id)  # this is safe even if fleet wasn't mine
                continue
            # TODO: check if currently in system and blockaded before accepting destination as location
            this_system_id = fleet.nextSystemID if fleet.nextSystemID != INVALID_ID else fleet.systemID
            dead_fleet = fleet_id in destroyed_object_ids
            if dead_fleet:
                self.delete_fleet_info(fleet_id)

            if fleet.ownedBy(empire_id):
                if not dead_fleet:
                    my_fleets_by_system.setdefault(this_system_id, []).append(fleet_id)
                    fleet_spot_position.setdefault(fleet.systemID, []).append(fleet_id)
                continue

            # TODO: consider checking death of individual ships.  If ships had been moved from this fleet
            # into another fleet, we might have witnessed their death in that other fleet but if this fleet
            # had not been seen since before that transfer then the ships might also still be listed here.
            if dead_fleet:
                continue

            # we are only interested in immediately recent data
            if get_partial_visibility_turn(fleet_id) < (current_turn - 1):
                continue

            sys_status = self.systemStatus.setdefault(this_system_id, {})
            sys_status['enemy_ship_count'] = sys_status.get('enemy_ship_count', 0) + len(fleet.shipIDs)
            enemies_by_system.setdefault(this_system_id, []).append(fleet_id)

            if not fleet.unowned:
                self.misc.setdefault('enemies_sighted', {}).setdefault(current_turn, []).append(fleet_id)

        # assess fleet and planet threats & my local fleets
        for sys_id in universe.systemIDs:
            sys_status = self.systemStatus.setdefault(sys_id, {})
            system = universe.getSystem(sys_id)
            if verbose:
                print "AIState threat evaluation for %s" % system
            # update fleets
            sys_status['myfleets'] = my_fleets_by_system.get(sys_id, [])
            sys_status['myFleetsAccessible'] = fleet_spot_position.get(sys_id, [])
            local_enemy_fleet_ids = enemies_by_system.get(sys_id, [])
            sys_status['localEnemyFleetIDs'] = local_enemy_fleet_ids
            if system:
                sys_status['name'] = system.name

            # update threats
            monster_ratings = []  # immobile
            enemy_ratings = []  # owned & mobile
            mob_ratings = []  # mobile & unowned
            mobile_fleets = []  # mobile and either owned or unowned
            for fid in local_enemy_fleet_ids:
                fleet = universe.getFleet(fid)  # ensured to exist
                fleet_rating = CombatRatingsAI.get_fleet_rating(
                    fid, enemy_stats=CombatRatingsAI.get_empire_standard_fighter())
                if fleet.speed == 0:
                    monster_ratings.append(fleet_rating)
                    if verbose:
                        print "\t immobile enemy fleet %s has rating %.1f" % (fleet, fleet_rating)
                    continue

                if verbose:
                    print "\t mobile enemy fleet %s has rating %.1f" % (fleet, fleet_rating)
                mobile_fleets.append(fid)
                if fleet.unowned:
                    mob_ratings.append(fleet_rating)
                else:
                    enemy_ratings.append(fleet_rating)

            enemy_rating = CombatRatingsAI.combine_ratings_list(enemy_ratings)
            monster_rating = CombatRatingsAI.combine_ratings_list(monster_ratings)
            mob_rating = CombatRatingsAI.combine_ratings_list(mob_ratings)
            lost_fleets = fleetsLostBySystem.get(sys_id, [])
            lost_fleet_rating = CombatRatingsAI.combine_ratings_list(lost_fleets)

            # under current visibility rules should not be possible to have any losses or other info here,
            # but just in case...
            partial_vis_turn = get_partial_visibility_turn(sys_id)
            if not system or partial_vis_turn < 0:
                if verbose:
                    print "Never had partial vis for %s - basing threat assessment on old info and lost ships" % system
                sys_status.setdefault('local_fleet_threats', set())
                sys_status['planetThreat'] = 0
                sys_status['fleetThreat'] = max(
                    CombatRatingsAI.combine_ratings(enemy_rating, mob_rating),
                    0.98 * sys_status.get('fleetThreat', 0),
                    1.1*lost_fleet_rating - monster_rating)
                sys_status['monsterThreat'] = max(
                    monster_rating,
                    0.98 * sys_status.get('monsterThreat', 0),
                    1.1*lost_fleet_rating - enemy_rating - mob_rating)
                sys_status['enemy_threat'] = max(
                    enemy_rating,
                    0.98 * sys_status.get('enemy_threat', 0),
                    1.1*lost_fleet_rating - monster_rating - mob_rating)
                sys_status['mydefenses'] = {'overall': 0, 'attack': 0, 'health': 0}
                sys_status['totalThreat'] = sys_status['fleetThreat']
                sys_status['regional_fleet_threats'] = sys_status['local_fleet_threats'].copy()
                continue

            # have either stale or current info
            pattack = phealth = 0
            mypattack = myphealth = 0
            for pid in system.planetIDs:
                planet = universe.getPlanet(pid)
                if not planet:
                    continue
                prating = self.assess_planet_threat(pid, sighting_age=current_turn - partial_vis_turn)
                if planet.ownedBy(empire_id):  # TODO: check for diplomatic status
                    mypattack += prating['attack']
                    myphealth += prating['health']
                else:
                    pattack += prating['attack']
                    phealth += prating['health']
                    if any("_NEST_" in special for special in planet.specials):
                        sys_status['nest_threat'] = 100
            sys_status['planetThreat'] = pattack * phealth
            sys_status['mydefenses'] = {'overall': mypattack * myphealth, 'attack': mypattack, 'health': myphealth}

            # previous threat assessment could account for losses, ignore the losses now
            if max(sys_status.get('totalThreat', 0), pattack * phealth) >= 0.6 * lost_fleet_rating:
                lost_fleet_rating = 0

            # TODO use sitrep combat info rather than estimating stealthed enemies by fleets lost to them
            # TODO also only consider past stealthed fleet threat to still be present if the system is still obstructed
            # TODO: track visibility across turns in order to distinguish the blip of visibility in (losing) combat,
            #       which FO currently treats as being for the previous turn,
            #       partially superseding the previous visibility for that turn

            if not partial_vis_turn == current_turn:
                sys_status.setdefault('local_fleet_threats', set())
                sys_status['currently_visible'] = False
                # print ("Stale visibility for system %d ( %s ) -- last seen %d, "
                #        "current Turn %d -- basing threat assessment on old info and lost ships") % (
                #     sys_id, sys_status.get('name', "name unknown"), partial_vis_turn, currentTurn)
                sys_status['fleetThreat'] = max(
                    CombatRatingsAI.combine_ratings(enemy_rating, mob_rating),
                    0.98 * sys_status.get('fleetThreat', 0),
                    2.0 * lost_fleet_rating - max(sys_status.get('monsterThreat', 0), monster_rating))
                sys_status['enemy_threat'] = max(
                    enemy_rating,
                    0.98 * sys_status.get('enemy_threat', 0),
                    1.1*lost_fleet_rating - max(sys_status.get('monsterThreat', 0), monster_rating))
                sys_status['monsterThreat'] = max(monster_rating, 0.98 * sys_status.get('monsterThreat', 0))
                # sys_status['totalThreat'] = ((pattack + enemy_attack + monster_attack) ** 0.8)\
                #                             * ((phealth + enemy_health + monster_health)** 0.6)  # reevaluate this
                sys_status['totalThreat'] = max(
                    CombatRatingsAI.combine_ratings_list([enemy_rating, mob_rating, monster_rating, pattack * phealth]),
                    2 * lost_fleet_rating,
                    0.98 * sys_status.get('totalThreat', 0))
            else:  # system considered visible
                sys_status['currently_visible'] = True
                sys_status['local_fleet_threats'] = set(mobile_fleets)
                # includes mobile monsters
                sys_status['fleetThreat'] = max(
                    CombatRatingsAI.combine_ratings(enemy_rating, mob_rating), 2*lost_fleet_rating - monster_rating)
                if verbose:
                    print "enemy threat calc parts: enemy rating %.1f, lost fleet rating %.1f, monster_rating %.1f" % (
                        enemy_rating, lost_fleet_rating, monster_rating)
                # does NOT include mobile monsters
                sys_status['enemy_threat'] = max(enemy_rating, 2*lost_fleet_rating - monster_rating)
                sys_status['monsterThreat'] = monster_rating
                sys_status['totalThreat'] = CombatRatingsAI.combine_ratings_list(
                    [enemy_rating, mob_rating, monster_rating, pattack * phealth])
            sys_status['regional_fleet_threats'] = sys_status['local_fleet_threats'].copy()
            sys_status['fleetThreat'] = max(sys_status['fleetThreat'], sys_status.get('nest_threat', 0))
            sys_status['totalThreat'] = max(sys_status['totalThreat'], sys_status.get('nest_threat', 0))

            # has been seen with Partial Vis, but is currently supply-blocked
            if partial_vis_turn > 0 and sys_id not in supply_unobstructed_systems:
                sys_status['fleetThreat'] = max(sys_status['fleetThreat'], min_hidden_attack * min_hidden_health)
                sys_status['totalThreat'] = max(
                    sys_status['totalThreat'],
                    ((pattack + min_hidden_attack) ** 0.8) * ((phealth + min_hidden_health) ** 0.6))
            if verbose and sys_status['fleetThreat'] > 0:
                print "%s intermediate status: %s" % (system, sys_status)

        enemy_supply, enemy_near_supply = self.assess_enemy_supply()  # TODO: assess change in enemy supply over time
        # assess secondary threats (threats of surrounding systems) and update my fleet rating
        for sys_id in universe.systemIDs:
            sys_status = self.systemStatus[sys_id]
            sys_status['enemies_supplied'] = enemy_supply.get(sys_id, [])
            sys_status['enemies_nearly_supplied'] = enemy_near_supply.get(sys_id, [])
            my_ratings_list = []
            my_ratings_against_planets_list = []
            for fid in sys_status['myfleets']:
                this_rating = self.get_rating(fid, True, self.get_standard_enemy())
                my_ratings_list.append(this_rating)
                my_ratings_against_planets_list.append(self.get_rating(fid, against_planets=True))
            if sys_id != INVALID_ID:
                sys_status['myFleetRating'] = CombatRatingsAI.combine_ratings_list(my_ratings_list)
                sys_status['myFleetRatingVsPlanets'] = CombatRatingsAI.combine_ratings_list(
                    my_ratings_against_planets_list)
                sys_status['all_local_defenses'] = CombatRatingsAI.combine_ratings(
                    sys_status['myFleetRating'], sys_status['mydefenses']['overall'])
            sys_status['neighbors'] = set(dict_from_map(universe.getSystemNeighborsMap(sys_id, self.empireID)))

        for sys_id in universe.systemIDs:
            sys_status = self.systemStatus[sys_id]
            neighbors = sys_status.get('neighbors', set())
            this_system = universe.getSystem(sys_id)
            if verbose:
                print "Regional Assessment for %s with local fleet threat %.1f" % (
                    this_system, sys_status.get('fleetThreat', 0))
            jumps2 = set()
            jumps3 = set()
            jumps4 = set()
            for seta, setb in [(neighbors, jumps2), (jumps2, jumps3), (jumps3, jumps4)]:
                for sys2id in seta:
                    setb.update(self.systemStatus.get(sys2id, {}).get('neighbors', set()))
            jump2ring = jumps2 - neighbors - {sys_id}
            jump3ring = jumps3 - jumps2 - neighbors - {sys_id}
            jump4ring = jumps4 - jumps3 - jumps2 - neighbors - {sys_id}
            sys_status['2jump_ring'] = jump2ring
            sys_status['3jump_ring'] = jump3ring
            sys_status['4jump_ring'] = jump4ring
            threat, max_threat, myrating, j1_threats = self.area_ratings(neighbors)
            sys_status['neighborThreat'] = threat
            sys_status['max_neighbor_threat'] = max_threat
            sys_status['my_neighbor_rating'] = myrating
            threat, max_threat, myrating, j2_threats = self.area_ratings(jump2ring)
            sys_status['jump2_threat'] = threat
            sys_status['my_jump2_rating'] = myrating
            threat, max_threat, myrating, j3_threats = self.area_ratings(jump3ring)
            sys_status['jump3_threat'] = threat
            sys_status['my_jump3_rating'] = myrating
            # for local system includes both enemies and mobs
            threat_keys = ['fleetThreat', 'neighborThreat', 'jump2_threat']
            sys_status['regional_threat'] = CombatRatingsAI.combine_ratings_list(
                [sys_status.get(x, 0) for x in threat_keys])
            # TODO: investigate cases where regional_threat has been nonzero but no regional_threat_fleets
            # (probably due to attenuating history of past threats)
            sys_status.setdefault('regional_fleet_threats', set()).update(j1_threats, j2_threats)
 def wrapper(*args):
     return dict_from_map(method(*args))
Ejemplo n.º 16
0
    def update_system_status(self):
        print 10 * "=", "Updating System Threats", 10 * "="
        universe = fo.getUniverse()
        empire = fo.getEmpire()
        empire_id = fo.empireID()
        destroyed_object_ids = universe.destroyedObjectIDs(empire_id)
        supply_unobstructed_systems = set(empire.supplyUnobstructedSystems)
        min_hidden_attack = 4
        min_hidden_health = 8

        # for use in debugging
        verbose = False

        # assess enemy fleets that may have been momentarily visible
        # start with dummy entries
        cur_e_fighters = {
            CombatRatingsAI.default_ship_stats().get_stats(hashable=True): [0]
        }
        old_e_fighters = {
            CombatRatingsAI.default_ship_stats().get_stats(hashable=True): [0]
        }
        enemies_by_system = {}
        my_fleets_by_system = {}
        fleet_spot_position = {}
        current_turn = fo.currentTurn()
        for fleet_id in universe.fleetIDs:
            fleet = universe.getFleet(fleet_id)
            if not fleet or fleet.empty:
                continue
            # TODO: check if currently in system and blockaded before accepting destination as location
            this_system_id = fleet.nextSystemID if fleet.nextSystemID != INVALID_ID else fleet.systemID
            dead_fleet = fleet_id in destroyed_object_ids

            if fleet.ownedBy(empire_id):
                if not dead_fleet:
                    my_fleets_by_system.setdefault(this_system_id,
                                                   []).append(fleet_id)
                    fleet_spot_position.setdefault(fleet.systemID,
                                                   []).append(fleet_id)
                continue

            # this is a fleet not owned by us
            if not fleet.unowned and (fleet.hasArmedShips
                                      or fleet.hasFighterShips):
                ship_stats = CombatRatingsAI.FleetCombatStats(
                    fleet_id).get_ship_stats(hashable=True)
                # track old/dead enemy fighters for rating assessments in case not enough current info
                e_f_dict = old_e_fighters if dead_fleet else cur_e_fighters
                for stats in ship_stats:
                    # log only ships that are armed
                    if stats[0]:
                        e_f_dict.setdefault(stats, [0])[0] += 1

            # TODO: consider checking death of individual ships.  If ships had been moved from this fleet
            # into another fleet, we might have witnessed their death in that other fleet but if this fleet
            # had not been seen since before that transfer then the ships might also still be listed here.
            if dead_fleet:
                continue

            # we are only interested in immediately recent data
            if get_partial_visibility_turn(fleet_id) < (current_turn - 1):
                continue

            sys_status = self.systemStatus.setdefault(this_system_id, {})
            sys_status['enemy_ship_count'] = sys_status.get(
                'enemy_ship_count', 0) + len(fleet.shipIDs)
            enemies_by_system.setdefault(this_system_id, []).append(fleet_id)

            if not fleet.unowned:
                self.misc.setdefault('enemies_sighted',
                                     {}).setdefault(current_turn,
                                                    []).append(fleet_id)

        # TODO: If no current information available, rate against own fighters
        e_f_dict = cur_e_fighters if len(
            cur_e_fighters) > 1 else old_e_fighters
        self.__empire_standard_enemy = sorted([
            (v, k) for k, v in e_f_dict.items()
        ])[-1][1]
        self.empire_standard_enemy_rating = self.get_standard_enemy(
        ).get_rating()

        # assess fleet and planet threats & my local fleets
        for sys_id in universe.systemIDs:
            sys_status = self.systemStatus.setdefault(sys_id, {})
            system = universe.getSystem(sys_id)
            if verbose:
                print "AIState threat evaluation for %s" % system
            # update fleets
            sys_status['myfleets'] = my_fleets_by_system.get(sys_id, [])
            sys_status['myFleetsAccessible'] = fleet_spot_position.get(
                sys_id, [])
            local_enemy_fleet_ids = enemies_by_system.get(sys_id, [])
            sys_status['localEnemyFleetIDs'] = local_enemy_fleet_ids
            if system:
                sys_status['name'] = system.name
                # TODO: double check are these checks/deletes necessary?
                for fid in system.fleetIDs:
                    fleet = universe.getFleet(fid)
                    if not fleet or fleet.empty or fid in destroyed_object_ids:
                        self.delete_fleet_info(
                            fid)  # this is safe even if fleet wasn't mine

            # update threats
            monster_ratings = []  # immobile
            enemy_ratings = []  # owned & mobile
            mob_ratings = []  # mobile & unowned
            mobile_fleets = []  # mobile and either owned or unowned
            for fid in local_enemy_fleet_ids:
                fleet = universe.getFleet(fid)  # ensured to exist
                fleet_rating = CombatRatingsAI.get_fleet_rating(
                    fid,
                    enemy_stats=CombatRatingsAI.get_empire_standard_fighter())
                if fleet.speed == 0:
                    monster_ratings.append(fleet_rating)
                    if verbose:
                        print "\t immobile enemy fleet %s has rating %.1f" % (
                            fleet, fleet_rating)
                    continue

                if verbose:
                    print "\t mobile enemy fleet %s has rating %.1f" % (
                        fleet, fleet_rating)
                mobile_fleets.append(fid)
                if fleet.unowned:
                    mob_ratings.append(fleet_rating)
                else:
                    enemy_ratings.append(fleet_rating)

            enemy_rating = CombatRatingsAI.combine_ratings_list(enemy_ratings)
            monster_rating = CombatRatingsAI.combine_ratings_list(
                monster_ratings)
            mob_rating = CombatRatingsAI.combine_ratings_list(mob_ratings)
            lost_fleets = fleetsLostBySystem.get(sys_id, [])
            lost_fleet_rating = CombatRatingsAI.combine_ratings_list(
                lost_fleets)

            # under current visibility rules should not be possible to have any losses or other info here,
            # but just in case...
            partial_vis_turn = get_partial_visibility_turn(sys_id)
            if not system or partial_vis_turn < 0:
                if verbose:
                    print "Never had partial vis for %s - basing threat assessment on old info and lost ships" % system
                sys_status.setdefault('local_fleet_threats', set())
                sys_status['planetThreat'] = 0
                sys_status['fleetThreat'] = max(
                    CombatRatingsAI.combine_ratings(enemy_rating, mob_rating),
                    0.98 * sys_status.get('fleetThreat', 0),
                    1.1 * lost_fleet_rating - monster_rating)
                sys_status['monsterThreat'] = max(
                    monster_rating, 0.98 * sys_status.get('monsterThreat', 0),
                    1.1 * lost_fleet_rating - enemy_rating - mob_rating)
                sys_status['enemy_threat'] = max(
                    enemy_rating, 0.98 * sys_status.get('enemy_threat', 0),
                    1.1 * lost_fleet_rating - monster_rating - mob_rating)
                sys_status['mydefenses'] = {
                    'overall': 0,
                    'attack': 0,
                    'health': 0
                }
                sys_status['totalThreat'] = sys_status['fleetThreat']
                sys_status['regional_fleet_threats'] = sys_status[
                    'local_fleet_threats'].copy()
                continue

            # have either stale or current info
            pattack = phealth = 0
            mypattack = myphealth = 0
            for pid in system.planetIDs:
                planet = universe.getPlanet(pid)
                if not planet:
                    continue
                prating = self.assess_planet_threat(pid,
                                                    sighting_age=current_turn -
                                                    partial_vis_turn)
                if planet.ownedBy(
                        empire_id):  # TODO: check for diplomatic status
                    mypattack += prating['attack']
                    myphealth += prating['health']
                else:
                    pattack += prating['attack']
                    phealth += prating['health']
                    if any("_NEST_" in special for special in planet.specials):
                        sys_status['nest_threat'] = 100
            sys_status['planetThreat'] = pattack * phealth
            sys_status['mydefenses'] = {
                'overall': mypattack * myphealth,
                'attack': mypattack,
                'health': myphealth
            }

            # previous threat assessment could account for losses, ignore the losses now
            if max(sys_status.get('totalThreat', 0),
                   pattack * phealth) >= 0.6 * lost_fleet_rating:
                lost_fleet_rating = 0

            # TODO use sitrep combat info rather than estimating stealthed enemies by fleets lost to them
            # TODO also only consider past stealthed fleet threat to still be present if the system is still obstructed
            # TODO: track visibility across turns in order to distinguish the blip of visibility in (losing) combat,
            #       which FO currently treats as being for the previous turn,
            #       partially superseding the previous visibility for that turn

            if not partial_vis_turn == current_turn:
                sys_status.setdefault('local_fleet_threats', set())
                sys_status['currently_visible'] = False
                # print ("Stale visibility for system %d ( %s ) -- last seen %d, "
                #        "current Turn %d -- basing threat assessment on old info and lost ships") % (
                #     sys_id, sys_status.get('name', "name unknown"), partial_vis_turn, currentTurn)
                sys_status['fleetThreat'] = max(
                    CombatRatingsAI.combine_ratings(enemy_rating, mob_rating),
                    0.98 * sys_status.get('fleetThreat', 0),
                    2.0 * lost_fleet_rating -
                    max(sys_status.get('monsterThreat', 0), monster_rating))
                sys_status['enemy_threat'] = max(
                    enemy_rating, 0.98 * sys_status.get('enemy_threat', 0),
                    1.1 * lost_fleet_rating -
                    max(sys_status.get('monsterThreat', 0), monster_rating))
                sys_status['monsterThreat'] = max(
                    monster_rating, 0.98 * sys_status.get('monsterThreat', 0))
                # sys_status['totalThreat'] = ((pattack + enemy_attack + monster_attack) ** 0.8)\
                #                             * ((phealth + enemy_health + monster_health)** 0.6)  # reevaluate this
                sys_status['totalThreat'] = max(
                    CombatRatingsAI.combine_ratings_list([
                        enemy_rating, mob_rating, monster_rating,
                        pattack * phealth
                    ]), 2 * lost_fleet_rating,
                    0.98 * sys_status.get('totalThreat', 0))
            else:  # system considered visible
                sys_status['currently_visible'] = True
                sys_status['local_fleet_threats'] = set(mobile_fleets)
                # includes mobile monsters
                sys_status['fleetThreat'] = max(
                    CombatRatingsAI.combine_ratings(enemy_rating, mob_rating),
                    2 * lost_fleet_rating - monster_rating)
                if verbose:
                    print "enemy threat calc parts: enemy rating %.1f, lost fleet rating %.1f, monster_rating %.1f" % (
                        enemy_rating, lost_fleet_rating, monster_rating)
                # does NOT include mobile monsters
                sys_status['enemy_threat'] = max(
                    enemy_rating, 2 * lost_fleet_rating - monster_rating)
                sys_status['monsterThreat'] = monster_rating
                sys_status[
                    'totalThreat'] = CombatRatingsAI.combine_ratings_list([
                        enemy_rating, mob_rating, monster_rating,
                        pattack * phealth
                    ])
            sys_status['regional_fleet_threats'] = sys_status[
                'local_fleet_threats'].copy()
            sys_status['fleetThreat'] = max(sys_status['fleetThreat'],
                                            sys_status.get('nest_threat', 0))
            sys_status['totalThreat'] = max(sys_status['totalThreat'],
                                            sys_status.get('nest_threat', 0))

            # has been seen with Partial Vis, but is currently supply-blocked
            if partial_vis_turn > 0 and sys_id not in supply_unobstructed_systems:
                sys_status['fleetThreat'] = max(
                    sys_status['fleetThreat'],
                    min_hidden_attack * min_hidden_health)
                sys_status['totalThreat'] = max(
                    sys_status['totalThreat'],
                    ((pattack + min_hidden_attack)**0.8) *
                    ((phealth + min_hidden_health)**0.6))
            if verbose and sys_status['fleetThreat'] > 0:
                print "%s intermediate status: %s" % (system, sys_status)

        enemy_supply, enemy_near_supply = self.assess_enemy_supply(
        )  # TODO: assess change in enemy supply over time
        # assess secondary threats (threats of surrounding systems) and update my fleet rating
        for sys_id in universe.systemIDs:
            sys_status = self.systemStatus[sys_id]
            sys_status['enemies_supplied'] = enemy_supply.get(sys_id, [])
            sys_status['enemies_nearly_supplied'] = enemy_near_supply.get(
                sys_id, [])
            my_ratings_list = []
            my_ratings_against_planets_list = []
            for fid in sys_status['myfleets']:
                this_rating = self.get_rating(fid, True,
                                              self.get_standard_enemy())
                my_ratings_list.append(this_rating)
                my_ratings_against_planets_list.append(
                    self.get_rating(fid, against_planets=True))
            if sys_id != INVALID_ID:
                sys_status[
                    'myFleetRating'] = CombatRatingsAI.combine_ratings_list(
                        my_ratings_list)
                sys_status[
                    'myFleetRatingVsPlanets'] = CombatRatingsAI.combine_ratings_list(
                        my_ratings_against_planets_list)
                sys_status[
                    'all_local_defenses'] = CombatRatingsAI.combine_ratings(
                        sys_status['myFleetRating'],
                        sys_status['mydefenses']['overall'])
            sys_status['neighbors'] = set(
                dict_from_map(
                    universe.getSystemNeighborsMap(sys_id, self.empireID)))

        for sys_id in universe.systemIDs:
            sys_status = self.systemStatus[sys_id]
            neighbors = sys_status.get('neighbors', set())
            this_system = universe.getSystem(sys_id)
            if verbose:
                print "Regional Assessment for %s with local fleet threat %.1f" % (
                    this_system, sys_status.get('fleetThreat', 0))
            jumps2 = set()
            jumps3 = set()
            jumps4 = set()
            for seta, setb in [(neighbors, jumps2), (jumps2, jumps3),
                               (jumps3, jumps4)]:
                for sys2id in seta:
                    setb.update(
                        self.systemStatus.get(sys2id,
                                              {}).get('neighbors', set()))
            jump2ring = jumps2 - neighbors - {sys_id}
            jump3ring = jumps3 - jumps2 - neighbors - {sys_id}
            jump4ring = jumps4 - jumps3 - jumps2 - neighbors - {sys_id}
            sys_status['2jump_ring'] = jump2ring
            sys_status['3jump_ring'] = jump3ring
            sys_status['4jump_ring'] = jump4ring
            threat, max_threat, myrating, j1_threats = self.area_ratings(
                neighbors)
            sys_status['neighborThreat'] = threat
            sys_status['max_neighbor_threat'] = max_threat
            sys_status['my_neighbor_rating'] = myrating
            threat, max_threat, myrating, j2_threats = self.area_ratings(
                jump2ring)
            sys_status['jump2_threat'] = threat
            sys_status['my_jump2_rating'] = myrating
            threat, max_threat, myrating, j3_threats = self.area_ratings(
                jump3ring)
            sys_status['jump3_threat'] = threat
            sys_status['my_jump3_rating'] = myrating
            # for local system includes both enemies and mobs
            threat_keys = ['fleetThreat', 'neighborThreat', 'jump2_threat']
            sys_status[
                'regional_threat'] = CombatRatingsAI.combine_ratings_list(
                    [sys_status.get(x, 0) for x in threat_keys])
            # TODO: investigate cases where regional_threat has been nonzero but no regional_threat_fleets
            # (probably due to attenuating history of past threats)
            sys_status.setdefault('regional_fleet_threats',
                                  set()).update(j1_threats, j2_threats)
Ejemplo n.º 17
0
def follow_vis_system_connections(start_system_id, home_system_id):
    universe = fo.getUniverse()
    empire_id = foAI.foAIstate.empireID
    exploration_list = [start_system_id]
    while exploration_list:
        cur_system_id = exploration_list.pop()
        if cur_system_id in graphFlags:
            continue
        graphFlags[cur_system_id] = 1
        system = universe.getSystem(cur_system_id)
        if not system:
            sys_name = foAI.foAIstate.systemStatus.get(cur_system_id, {}).get('name', "name unknown")
        else:
            sys_name = system.name or foAI.foAIstate.systemStatus.get(cur_system_id, {}).get('name', "name unknown")
        if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
            pre_vis = "a border system"
        elif cur_system_id in foAI.foAIstate.visInteriorSystemIDs:
            pre_vis = "an interior system"
        else:
            pre_vis = "an unknown 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 = ['%s: %s' % (vis.name, turn) for vis, turn in visibility_turn_list]
            print "*** system ID %d ( %s ) ; previously %s, new visibility turns info: %s " % (cur_system_id, sys_name, pre_vis, visibility_info)
        status_str = "*** system ID %d ( %s ) ; " % (cur_system_id, sys_name)
        has_been_visible = universe.getVisibilityTurnsMap(cur_system_id, empire_id).get(fo.visibility.partial, 0) > 0
        is_connected = universe.systemsConnected(cur_system_id, home_system_id, -1)  # self.empire_id)
        status_str += " -- is %s partially visible " % (["not", ""][has_been_visible])
        status_str += " -- is %s visibly connected to homesystem " % (["not", ""][is_connected])
        if has_been_visible:
            sys_status = foAI.foAIstate.systemStatus.setdefault(cur_system_id, {})
            foAI.foAIstate.visInteriorSystemIDs[cur_system_id] = 1
            if cur_system_id in foAI.foAIstate.visBorderSystemIDs:
                del foAI.foAIstate.visBorderSystemIDs[cur_system_id]
            #neighbors= dict( [(el.key(), el.data()) for el in universe.getSystemNeighborsMap(cur_system_id, empire_id)] )  #
            neighbors = set(dict_from_map(universe.getSystemNeighborsMap(cur_system_id, empire_id)).keys())
            sys_status.setdefault('neighbors', set()).update(neighbors)
            sys_planets = sys_status.setdefault('planets', {})
            if fo.currentTurn() < 50:
                print "    previously knew of system %d planets %s" % (cur_system_id, sys_planets.keys())
            if system:
                for planet_id in system.planetIDs:
                    sys_planets.setdefault(planet_id, {}).setdefault(TARGET_POP, 0)
                    sys_planets[planet_id].setdefault(TROOPS, 0)
                    planet = universe.getPlanet(planet_id)

                    if planet:
                        new_pop = planet.currentMeterValue(fo.meterType.targetPopulation)
                        if new_pop != sys_planets[planet_id][TARGET_POP]:
                            if fo.currentTurn() < 50:
                                print "  * updating targetPop of planet %d ( %s ) to %.2f from %.2f" % (planet_id, planet.name, new_pop, sys_planets[planet_id][TARGET_POP])
                        troops = planet.currentMeterValue(fo.meterType.troops)
                        if troops != sys_planets[planet_id].get(TROOPS, 0):
                            if fo.currentTurn() < 50:
                                print "  * updating troops of planet %d ( %s ) to %.2f from %.2f" % (planet_id, planet.name, troops, sys_planets[planet_id][
                                    TROOPS])
                        sys_planets[planet_id][TARGET_POP] = new_pop
                        sys_planets[planet_id][TROOPS] = troops
            if fo.currentTurn() < 50:
                print "    now know of system %d planets %s" % (cur_system_id, sys_planets.keys())
            #neighbors = list( universe.getImmediateNeighbors(cur_system_id, empire_id) )  #imNeighbors
            #if set(neighbors) != set(neighbors2):
            # print "Error with neighbors: imn giving %s ; giN giving %s"%(neighbors2, neighbors)
            if neighbors:
                status_str += " -- has neighbors %s " % neighbors
                for sys_id in neighbors:
                    if sys_id not in foAI.foAIstate.exploredSystemIDs:
                        foAI.foAIstate.unexploredSystemIDs[sys_id] = 1
                    if (sys_id not in graphFlags) and (sys_id not in foAI.foAIstate.visInteriorSystemIDs):
                        foAI.foAIstate.visBorderSystemIDs[sys_id] = 1
                        exploration_list.append(sys_id)
        if fo.currentTurn() < 50:
            print status_str
            print "----------------------------------------------------------"
Ejemplo n.º 18
0
    def is_valid(self):
        """check if FleetOrder could be somehow in future issued = is valid"""

        if self.is_executed() and self.is_execution_completed():
            return False
        if self.get_source_target().valid and self.get_target_target().valid:
            sourceAITargetTypeValid = False
            targetAITargetTypeValid = False
            universe = fo.getUniverse()

            # outpost
            if AIFleetOrderType.ORDER_OUTPOST == self.get_fleet_order_type():
                # with ship
                if AITargetType.TARGET_SHIP == self.get_source_target().target_type:
                    ship = universe.getShip(self.get_source_target().target_id)
                    if ship.canColonize:
                        sourceAITargetTypeValid = True
                # with fleet
                elif AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    fleet = universe.getFleet(self.get_source_target().target_id)
                    if fleet.hasOutpostShips:
                        sourceAITargetTypeValid = True
                # colonise planet
                if AITargetType.TARGET_PLANET == self.get_target_target().target_type:
                    planet = universe.getPlanet(self.get_target_target().target_id)
                    system = universe.getSystem(planet.systemID)
                    sysPartialVisTurn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, fo.empireID())).get(fo.visibility.partial, -9999)
                    planetPartialVisTurn = dict_from_map(universe.getVisibilityTurnsMap(planet.id, fo.empireID())).get(fo.visibility.partial, -9999)
                    if (planetPartialVisTurn == sysPartialVisTurn) and planet.unowned:
                        targetAITargetTypeValid = True
                    else:#try to get order cancelled out
                        self.__set_executed()
                        self.__set_execution_completed()

            # colonise
            elif AIFleetOrderType.ORDER_COLONISE == self.get_fleet_order_type():
                # with ship
                if AITargetType.TARGET_SHIP == self.get_source_target().target_type:
                    ship = universe.getShip(self.get_source_target().target_id)
                    if ship.canColonize:
                        sourceAITargetTypeValid = True
                # with fleet
                elif AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    fleet = universe.getFleet(self.get_source_target().target_id)
                    if fleet.hasColonyShips:
                        sourceAITargetTypeValid = True
                # colonise planet
                if AITargetType.TARGET_PLANET == self.get_target_target().target_type:
                    planet = universe.getPlanet(self.get_target_target().target_id)
                    system = universe.getSystem(planet.systemID)
                    sysPartialVisTurn = dict_from_map(universe.getVisibilityTurnsMap(planet.systemID, fo.empireID())).get(fo.visibility.partial, -9999)
                    planetPartialVisTurn = dict_from_map(universe.getVisibilityTurnsMap(planet.id, fo.empireID())).get(fo.visibility.partial, -9999)

                    if (planetPartialVisTurn == sysPartialVisTurn) and ( planet.unowned or (planet.ownedBy(fo.empireID()) and planet.currentMeterValue(fo.meterType.population)==0 )):
                        targetAITargetTypeValid = True
                    else:#try to get order cancelled out
                        self.__set_executed()
                        self.__set_execution_completed()
            # invade
            elif AIFleetOrderType.ORDER_INVADE == self.get_fleet_order_type():
                # with ship
                if AITargetType.TARGET_SHIP == self.get_source_target().target_type:
                    ship = universe.getShip(self.get_source_target().target_id)
                    if ship.canInvade:
                        sourceAITargetTypeValid = True
                # with fleet
                elif AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    fleet = universe.getFleet(self.get_source_target().target_id)
                    if fleet.hasTroopShips:
                        sourceAITargetTypeValid = True
                # invade planet
                if AITargetType.TARGET_PLANET == self.get_target_target().target_type:
                    planet = universe.getPlanet(self.get_target_target().target_id)
                    planetPopulation = planet.currentMeterValue(fo.meterType.population)
                    if not planet.unowned or planetPopulation > 0:
                        targetAITargetTypeValid = True
                    else:#try to get order cancelled out
                        self.__set_executed()
                        self.__set_execution_completed()
            # military
            elif AIFleetOrderType.ORDER_MILITARY == self.get_fleet_order_type():
                # with ship
                if AITargetType.TARGET_SHIP == self.get_source_target().target_type:
                    ship = universe.getShip(self.get_source_target().target_id)
                    if ship.isArmed:
                        sourceAITargetTypeValid = True
                # with fleet
                elif AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    fleet = universe.getFleet(self.get_source_target().target_id)
                    if fleet.hasArmedShips:
                        sourceAITargetTypeValid = True
                # military system
                if AITargetType.TARGET_SYSTEM == self.get_target_target().target_type:
                    system = universe.getSystem(self.get_target_target().target_id)
                    targetAITargetTypeValid = True
            # move
            elif AIFleetOrderType.ORDER_MOVE == self.get_fleet_order_type():
                # with fleet
                if AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    sourceAITargetTypeValid = True
                # move to system
                if AITargetType.TARGET_SYSTEM == self.get_target_target().target_type:
                    targetAITargetTypeValid = True
            # resupply
            elif AIFleetOrderType.ORDER_RESUPPLY == self.get_fleet_order_type():
                # with fleet
                if AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    sourceAITargetTypeValid = True
                # move to system
                if AITargetType.TARGET_SYSTEM == self.get_target_target().target_type:
                    empire = fo.getEmpire()
                    fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
                    if self.get_target_target().target_id in fleetSupplyableSystemIDs:
                        targetAITargetTypeValid = True
            # repair
            elif AIFleetOrderType.ORDER_REPAIR == self.get_fleet_order_type():
                # with fleet
                if AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    sourceAITargetTypeValid = True
                # move to system
                if AITargetType.TARGET_SYSTEM == self.get_target_target().target_type:
                    empire = fo.getEmpire()
                    fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
                    if self.get_target_target().target_id in fleetSupplyableSystemIDs: #TODO: check for drydock still there/owned
                        targetAITargetTypeValid = True
            # split fleet
            elif AIFleetOrderType.ORDER_SPLIT_FLEET == self.get_fleet_order_type():
                # with fleet
                if AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    sourceAITargetTypeValid = True
                # split ship
                if AITargetType.TARGET_SHIP == self.get_target_target().target_type:
                    targetAITargetTypeValid = True
                if sourceAITargetTypeValid == True and targetAITargetTypeValid == True:
                    if self.__check_validity_ship_in_fleet(self.get_target_target(), self.get_source_target()):
                        return True
            elif AIFleetOrderType.ORDER_ATTACK == self.get_fleet_order_type():
                # with fleet
                if AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    sourceAITargetTypeValid = True
                # move to system
                if AITargetType.TARGET_SYSTEM == self.get_target_target().target_type or AITargetType.TARGET_PLANET == self.get_target_target().target_type:
                    targetAITargetTypeValid = True
            elif AIFleetOrderType.ORDER_DEFEND == self.get_fleet_order_type():
                # with fleet
                if AITargetType.TARGET_FLEET == self.get_source_target().target_type:
                    sourceAITargetTypeValid = True
                # move to system
                if AITargetType.TARGET_SYSTEM == self.get_target_target().target_type or AITargetType.TARGET_PLANET == self.get_target_target().target_type:
                    targetAITargetTypeValid = True

            if sourceAITargetTypeValid == True and targetAITargetTypeValid == True:
                return True

        return False