コード例 #1
0
def send_colony_ships(colony_fleet_ids, evaluated_planets, mission_type):
    """sends a list of colony ships to a list of planet_value_pairs"""
    fleet_pool = colony_fleet_ids[:]
    try_all = False
    if mission_type == MissionType.OUTPOST:
        cost = 20 + outpod_pod_cost()
    else:
        try_all = True
        cost = 20 + colony_pod_cost_turns()[1]
        if fo.currentTurn() < 50:
            cost *= 0.4  # will be making fast tech progress so value is underestimated
        elif fo.currentTurn() < 80:
            cost *= 0.8  # will be making fast-ish tech progress so value is underestimated

    potential_targets = [
        (pid, (score, specName))
        for (pid, (score, specName)) in evaluated_planets
        if score > (0.8 * cost) and score > MINIMUM_COLONY_SCORE
    ]

    debug("Colony/outpost ship matching: fleets %s to planets %s" % (fleet_pool, evaluated_planets))

    if try_all:
        debug("Trying best matches to current colony ships")
        best_scores = dict(evaluated_planets)
        potential_targets = []
        for pid, ratings in _all_colony_opportunities.items():
            for rating in ratings:
                if rating[0] >= 0.75 * best_scores.get(pid, [9999])[0]:
                    potential_targets.append((pid, rating))
        potential_targets.sort(key=itemgetter(1), reverse=True)

    # added a lot of checking because have been getting mysterious exception, after too many recursions to get info
    fleet_pool = set(fleet_pool)
    universe = fo.getUniverse()
    for fid in fleet_pool:
        fleet = universe.getFleet(fid)
        if not fleet or fleet.empty:
            warning("Bad fleet ( ID %d ) given to colonization routine; will be skipped" % fid)
            fleet_pool.remove(fid)
            continue
        report_str = "Fleet ID (%d): %d ships; species: " % (fid, fleet.numShips)
        for sid in fleet.shipIDs:
            ship = universe.getShip(sid)
            if not ship:
                report_str += "NoShip, "
            else:
                report_str += "%s, " % ship.speciesName
        debug(report_str)
    debug("")
    already_targeted = []
    # for planetID_value_pair in evaluatedPlanets:
    aistate = get_aistate()
    while fleet_pool and potential_targets:
        target = potential_targets.pop(0)
        if target in already_targeted:
            continue
        planet_id = target[0]
        if planet_id in already_targeted:
            continue
        planet = universe.getPlanet(planet_id)
        sys_id = planet.systemID
        if (
            aistate.systemStatus.setdefault(sys_id, {}).setdefault("monsterThreat", 0) > 2000
            or fo.currentTurn() < 20
            and aistate.systemStatus[sys_id]["monsterThreat"] > 200
        ):
            debug(
                "Skipping colonization of system %s due to Big Monster, threat %d"
                % (universe.getSystem(sys_id), aistate.systemStatus[sys_id]["monsterThreat"])
            )
            already_targeted.append(planet_id)
            continue

        # make sure not to run into stationary guards
        if ExplorationAI.system_could_have_unknown_stationary_guard(sys_id):
            ExplorationAI.request_emergency_exploration(sys_id)
            continue

        this_spec = target[1][1]
        found_fleets = []
        try:
            this_fleet_list = FleetUtilsAI.get_fleets_for_mission(
                target_stats={},
                min_stats={},
                cur_stats={},
                starting_system=sys_id,
                species=this_spec,
                fleet_pool_set=fleet_pool,
                fleet_list=found_fleets,
            )
        except Exception as e:
            error(e, exc_info=True)
            continue
        if not this_fleet_list:
            fleet_pool.update(found_fleets)  # just to be safe
            continue  # must have no compatible colony/outpost ships
        fleet_id = this_fleet_list[0]
        already_targeted.append(planet_id)
        ai_target = TargetPlanet(planet_id)
        aistate.get_fleet_mission(fleet_id).set_target(mission_type, ai_target)
コード例 #2
0
    def issue_order(self):
        if not super(OrderInvade, self).can_issue_order():
            return False

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

        invasion_roles = (ShipRoleType.BASE_INVASION,
                          ShipRoleType.MILITARY_INVASION)

        debug("Issuing order: %s fleet: %s target: %s" %
              (self.ORDER_NAME, self.fleet, self.target))
        # will track if at least one invasion troops successfully deployed
        result = True
        aistate = get_aistate()
        overkill_margin = 2  # TODO: get from character module; allows a handful of extra troops to be immediately
        #                            defending planet
        # invasion orders processed before regen takes place, so use initialMeterValue() here
        troops_wanted = planet.initialMeterValue(
            fo.meterType.troops) + overkill_margin
        troops_already_assigned = 0  # TODO: get from other fleets in same system
        troops_assigned = 0
        # Todo: evaluate all local troop ships (including other fleets) before using any, make sure base invasion troops
        #       are used first, and that not too many altogether are used (choosing an optimal collection to use).
        for invasion_role in invasion_roles:  # first checks base troops, then regular
            if not result:
                break
            for ship_id in fleet.shipIDs:
                if troops_already_assigned + troops_assigned >= troops_wanted:
                    break
                ship = universe.getShip(ship_id)
                if aistate.get_ship_role(ship.design.id) != invasion_role:
                    continue

                debug("Ordering troop ship %d to invade %s" %
                      (ship_id, planet))
                result = fo.issueInvadeOrder(ship_id, planet_id) and result
                if not result:
                    shields = planet.currentMeterValue(fo.meterType.shield)
                    planet_stealth = planet.currentMeterValue(
                        fo.meterType.stealth)
                    pop = planet.currentMeterValue(fo.meterType.population)
                    warning("Invasion order failed!")
                    debug(
                        " -- planet has %.1f stealth, shields %.1f, %.1f population and "
                        "is owned by empire %d" %
                        (planet_stealth, shields, pop, planet.owner))
                    if "needsEmergencyExploration" not in dir(aistate):
                        aistate.needsEmergencyExploration = []

                    # TODO: Check if this even makes sense - to invade a planet the ship must be in the system
                    #       which should grant the same visibility as a scout ship...
                    ExplorationAI.request_emergency_exploration(fleet.systemID)
                    debug(
                        "Due to trouble invading, added system %d to Emergency Exploration List"
                        % fleet.systemID)
                    self.executed = False
                    # debug(universe.getPlanet(planet_id).dump())  # TODO: fix fo.UniverseObject.dump()
                    break
                troops_assigned += ship.troopCapacity
        # TODO: split off unused troop ships into new fleet and give new orders this cycle
        if result:
            debug("Successfully ordered %d troopers to invade %s" %
                  (troops_assigned, planet))
            return True
        else:
            return False