Example #1
0
    def generateAIFleetOrders(self):
        "generates AIFleetOrders from fleets targets to accomplish"

        universe = fo.getUniverse()
        fleetID = self.target_id
        fleet = universe.getFleet(fleetID)
        if (not fleet) or fleet.empty or (fleetID in universe.destroyedObjectIDs(fo.empireID())): #fleet was probably merged into another or was destroyed
            foAI.foAIstate.deleteFleetInfo(fleetID)
            return

        # TODO: priority
        self.clearAIFleetOrders()
        systemID = fleet.systemID
        start_sys_id = [ fleet.nextSystemID,  systemID ][ systemID >= 0 ]
        # if fleet doesn't have any mission, then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
        #if (not self.hasAnyAIMissionTypes()):
        ntargets=0
        for aiFleetMissionType in self.getAIMissionTypes():
            ntargets += len( self.getAITargets(aiFleetMissionType) )
        if (ntargets ==0) and (systemID not in  set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs + 
                                                    AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs)  ):
            if self.need_repair():
                repairAIFleetOrder = MoveUtilsAI.getRepairAIFleetOrder(self.getAITarget(), start_sys_id)
                if repairAIFleetOrder.isValid():
                    self.appendAIFleetOrder(repairAIFleetOrder)
            if not(self.getLocationAITarget().target_id in fleetSupplyableSystemIDs):
                resupplyAIFleetOrder = MoveUtilsAI.getResupplyAIFleetOrder(self.getAITarget(), self.getLocationAITarget())
                if resupplyAIFleetOrder.isValid():
                    self.appendAIFleetOrder(resupplyAIFleetOrder)
            return #no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        systemAITargets = self.__getRequiredToVisitSystemAITargets()
        aiFleetOrdersToVisitSystems = MoveUtilsAI.getAIFleetOrdersFromSystemAITargets(self.getAITarget(), systemAITargets)
        #TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
        #print "----------------------------------------"
        #print "*+*+ fleet %d :  has fleet action system targets:  %s"%(fleetID,  [str(obj) for obj in systemAITargets])
        #print "----------"
        #print "*+*+ fleet %d:  has movement  orders:  %s"%(fleetID,  [str(obj) for obj in aiFleetOrdersToVisitSystems])

        for aiFleetOrder in aiFleetOrdersToVisitSystems:
            self.appendAIFleetOrder(aiFleetOrder)

        # if fleet is in some system = fleet.systemID >=0, then also generate system AIFleetOrders
        if systemID >= 0:
            # system in where fleet is
            systemAITarget = AITarget.AITarget(EnumsAI.AITargetType.TARGET_SYSTEM, systemID)
            # if mission aiTarget has required system where fleet is, then generate aiFleetOrder from this aiTarget
            aiMissionTypes = self.getAIMissionTypes()
            # for all targets in all mission types get required systems to visit
            for aiFleetMissionType in aiMissionTypes:
                aiTargets = self.getAITargets(aiFleetMissionType)
                for aiTarget in aiTargets:
                    if systemAITarget in aiTarget.get_required_system_ai_targets():
                        # from target required to visit get fleet orders to accomplish target
                        aiFleetOrder = self.__getAIFleetOrderFromAITarget(aiFleetMissionType, aiTarget)
                        self.appendAIFleetOrder(aiFleetOrder)
Example #2
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (
                fleet_id in universe.destroyedObjectIDs(fo.empireID())
        ):  # fleet was probably merged into another or was destroyed
            foAI.foAIstate.delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission, then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        # if (not self.hasAnyAIMissionTypes()):
        if not self.target and (system_id
                                not in set(AIstate.colonyTargetedSystemIDs +
                                           AIstate.outpostTargetedSystemIDs +
                                           AIstate.invasionTargetedSystemIDs +
                                           AIstate.blockadeTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(
                    self.fleet, start_sys_id)
                if repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            if fleet.fuel < fleet.maxFuel and self.get_location_target(
            ).id not in fleet_supplyable_system_ids:
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(
                    self.fleet, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        if self.target:
            system_targets_required_to_visit = [self.target.get_system()]
            orders_to_visit_systems = MoveUtilsAI.get_fleet_orders_from_system_targets(
                self.fleet, system_targets_required_to_visit)
            # TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
            for fleet_order in orders_to_visit_systems:
                self.orders.append(fleet_order)

        # if fleet is in some system = fleet.system_id >=0, then also generate system AIFleetOrders
        if system_id >= 0 and self.target:
            # system in where fleet is
            system_target = System(system_id)
            # if mission aiTarget has required system where fleet is, then generate fleet_order from this aiTarget
            # for all targets in all mission types get required systems to visit
            if system_target == self.target.get_system():
                # from target required to visit get fleet orders to accomplish target
                fleet_order = self._get_fleet_order_from_target(
                    self.type, self.target)
                self.orders.append(fleet_order)
Example #3
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (fleet_id
                                          in universe.destroyedObjectIDs(
                                              fo.empireID())):
            # fleet was probably merged into another or was destroyed
            foAI.foAIstate.delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission,
        # then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        # if (not self.hasAnyAIMissionTypes()):
        if not self.target and (system_id
                                not in set(AIstate.colonyTargetedSystemIDs +
                                           AIstate.outpostTargetedSystemIDs +
                                           AIstate.invasionTargetedSystemIDs +
                                           AIstate.blockadeTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(
                    self.fleet, start_sys_id)
                if repair_fleet_order and repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            cur_fighter_capacity, max_fighter_capacity = FleetUtilsAI.get_fighter_capacity_of_fleet(
                fleet_id)
            if (fleet.fuel < fleet.maxFuel
                    or cur_fighter_capacity < max_fighter_capacity
                    and self.get_location_target().id
                    not in fleet_supplyable_system_ids):
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(
                    self.fleet, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

        if self.target:
            # for some targets fleet has to visit systems and therefore fleet visit them
            system_to_visit = self.target.get_system()
            orders_to_visit_systems = MoveUtilsAI.create_move_orders_to_system(
                self.fleet, system_to_visit)
            # TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
            for fleet_order in orders_to_visit_systems:
                self.orders.append(fleet_order)

            # also generate appropriate final orders
            fleet_order = self._get_fleet_order_from_target(
                self.type, self.target)
            self.orders.append(fleet_order)
Example #4
0
    def generateAIFleetOrders(self):
        "generates AIFleetOrders from fleets targets to accomplish"

        universe = fo.getUniverse()
        fleetID = self.getAITargetID()
        fleet = universe.getFleet(fleetID)
        if (not fleet) or fleet.empty or (fleetID in universe.destroyedObjectIDs(fo.empireID())): #fleet was probably merged into another or was destroyed
            foAI.foAIstate.deleteFleetInfo(fleetID)
            return

        # TODO: priority
        self.clearAIFleetOrders()
        ntargets=0
        for aiFleetMissionType in self.getAIMissionTypes():
            ntargets += len( self.getAITargets(aiFleetMissionType) )
        if ntargets ==0:
            return #no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        systemAITargets = self.__getRequiredToVisitSystemAITargets()
        aiFleetOrdersToVisitSystems = MoveUtilsAI.getAIFleetOrdersFromSystemAITargets(self.getAITarget(), systemAITargets)
        #print "----------------------------------------"
        #print "*+*+ fleet %d :  has fleet action system targets:  %s"%(fleetID,  [str(obj) for obj in systemAITargets])
        #print "----------"
        #print "*+*+ fleet %d:  has movement  orders:  %s"%(fleetID,  [str(obj) for obj in aiFleetOrdersToVisitSystems])

        for aiFleetOrder in aiFleetOrdersToVisitSystems:
            self.appendAIFleetOrder(aiFleetOrder)

        # if fleet is in some system = fleet.systemID >=0, then also generate system AIFleetOrders
        systemID = fleet.systemID
        if systemID >= 0:
            # system in where fleet is
            systemAITarget = AITarget.AITarget(AITargetType.TARGET_SYSTEM, systemID)
            # if mission aiTarget has required system where fleet is, then generate aiFleetOrder from this aiTarget 
            aiMissionTypes = self.getAIMissionTypes()
            # for all targets in all mission types get required systems to visit 
            for aiFleetMissionType in aiMissionTypes:
                aiTargets = self.getAITargets(aiFleetMissionType)
                for aiTarget in aiTargets:
                    if systemAITarget in aiTarget.getRequiredSystemAITargets():
                        # from target required to visit get fleet orders to accomplish target
                        aiFleetOrder = self.__getAIFleetOrderFromAITarget(aiFleetMissionType, aiTarget)
                        self.appendAIFleetOrder(aiFleetOrder)


        # if fleet don't have any mission, then resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
        if (not self.hasAnyAIMissionTypes()) and not(self.getLocationAITarget().getTargetID() in fleetSupplyableSystemIDs):
            resupplyAIFleetOrder = MoveUtilsAI.getResupplyAIFleetOrder(self.getAITarget(), self.getLocationAITarget())
            if resupplyAIFleetOrder.isValid():
                self.appendAIFleetOrder(resupplyAIFleetOrder)
Example #5
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (fleet_id in universe.destroyedObjectIDs(fo.empireID())):  # fleet was probably merged into another or was destroyed
            foAI.foAIstate.delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission, then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        # if (not self.hasAnyAIMissionTypes()):
        if not self.target and (system_id not in set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs +
                                                     AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(self.fleet, start_sys_id)
                if repair_fleet_order and repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            cur_fighter_capacity, max_fighter_capacity = FleetUtilsAI.get_fighter_capacity_of_fleet(fleet_id)
            if (fleet.fuel < fleet.maxFuel or cur_fighter_capacity < max_fighter_capacity
                    and self.get_location_target().id not in fleet_supplyable_system_ids):
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(self.fleet, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        if self.target:
            system_targets_required_to_visit = [self.target.get_system()]
            orders_to_visit_systems = MoveUtilsAI.get_fleet_orders_from_system_targets(self.fleet, system_targets_required_to_visit)
            # TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
            for fleet_order in orders_to_visit_systems:
                self.orders.append(fleet_order)

        # if fleet is in some system = fleet.system_id >=0, then also generate system AIFleetOrders
        if system_id >= 0 and self.target:
            # system in where fleet is
            system_target = System(system_id)
            # if mission aiTarget has required system where fleet is, then generate fleet_order from this aiTarget
            # for all targets in all mission types get required systems to visit
            if system_target == self.target.get_system():
                # from target required to visit get fleet orders to accomplish target
                fleet_order = self._get_fleet_order_from_target(self.type, self.target)
                self.orders.append(fleet_order)
Example #6
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.fleet.id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (fleet_id in universe.destroyedObjectIDs(fo.empireID())):
            # fleet was probably merged into another or was destroyed
            get_aistate().delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission,
        # then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        # if (not self.hasAnyAIMissionTypes()):
        if not self.target and (system_id not in set(AIstate.colonyTargetedSystemIDs +
                                                     AIstate.outpostTargetedSystemIDs +
                                                     AIstate.invasionTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(self.fleet, start_sys_id)
                if repair_fleet_order and repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            cur_fighter_capacity, max_fighter_capacity = FleetUtilsAI.get_fighter_capacity_of_fleet(fleet_id)
            if (fleet.fuel < fleet.maxFuel or cur_fighter_capacity < max_fighter_capacity
                    and self.get_location_target().id not in fleet_supplyable_system_ids):
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(self.fleet, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

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

            system_to_visit = (self.target.get_system() if not self.type == MissionType.PROTECT_REGION
                               else TargetSystem(self._get_target_for_protection_mission()))
            if not system_to_visit:
                return
            orders_to_visit_systems = MoveUtilsAI.create_move_orders_to_system(self.fleet, system_to_visit)
            # TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
            for fleet_order in orders_to_visit_systems:
                self.orders.append(fleet_order)

            # also generate appropriate final orders
            fleet_order = self._get_fleet_order_from_target(self.type, self.target)
            self.orders.append(fleet_order)
Example #7
0
    def _need_repair(self, repair_limit=0.70):
        """Check if fleet needs to be repaired.

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

         :param repair_limit: percentage of health below which the fleet is sent to repair
         :type repair_limit: float
         :return: True if fleet needs repair
         :rtype: bool
        """
        # TODO: More complex evaluation if fleet needs repair (consider self-repair, distance, threat, mission...)
        fleet_id = self.fleet.id
        # if we are already at a system where we can repair, make sure we use it...
        system = self.fleet.get_system()
        # TODO starlane obstruction is not considered in the next call
        nearest_dock = MoveUtilsAI.get_best_drydock_system_id(system.id, fleet_id)
        if nearest_dock == system.id:
            repair_limit = 0.99
        # if combat fleet, use military repair check
        if get_aistate().get_fleet_role(fleet_id) in COMBAT_MISSION_TYPES:
            return fleet_id in MilitaryAI.avail_mil_needing_repair([fleet_id], on_mission=bool(self.orders),
                                                                   repair_limit=repair_limit)[0]
        # TODO: Allow to split fleet to send only damaged ships to repair
        ships_cur_health, ships_max_health = FleetUtilsAI.get_current_and_max_structure(fleet_id)
        return ships_cur_health < repair_limit * ships_max_health
Example #8
0
 def issue_order(self):
     if not super(OrderRepair, self).issue_order():
         return False
     fleet_id = self.fleet.id
     system_id = self.target.get_system().id
     fleet = self.fleet.get_object()  # type: fo.fleet
     if system_id == fleet.systemID:
         aistate = get_aistate()
         if aistate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
             if system_id in aistate.needsEmergencyExploration:
                 aistate.needsEmergencyExploration.remove(system_id)
     elif system_id != fleet.nextSystemID:
         fo.issueAggressionOrder(fleet_id, False)
         start_id = FleetUtilsAI.get_fleet_system(fleet)
         dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(
             fleet_id, start_id, system_id)
         universe = fo.getUniverse()
         debug(
             "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s"
             % (fleet_id, self.ORDER_NAME, universe.getSystem(dest_id),
                universe.getSystem(system_id)))
         fo.issueFleetMoveOrder(fleet_id, dest_id)
         debug("Order issued: %s fleet: %s target: %s" %
               (self.ORDER_NAME, self.fleet, self.target))
     ships_cur_health, ships_max_health = FleetUtilsAI.get_current_and_max_structure(
         fleet_id)
     self.executed = (ships_cur_health == ships_max_health)
     return True
Example #9
0
    def _need_repair(self, repair_limit=0.70):
        """Check if fleet needs to be repaired.

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

         :param repair_limit: percentage of health below which the fleet is sent to repair
         :type repair_limit: float
         :return: True if fleet needs repair
         :rtype: bool
        """
        # TODO: More complex evaluation if fleet needs repair (consider self-repair, distance, threat, mission...)
        fleet_id = self.fleet.id
        # if we are already at a system where we can repair, make sure we use it...
        system = self.fleet.get_system()
        # TODO starlane obstruction is not considered in the next call
        nearest_dock = MoveUtilsAI.get_best_drydock_system_id(
            system.id, fleet_id)
        if nearest_dock == system.id:
            repair_limit = 0.99
        # if combat fleet, use military repair check
        if get_aistate().get_fleet_role(fleet_id) in COMBAT_MISSION_TYPES:
            return fleet_id in MilitaryAI.avail_mil_needing_repair(
                [fleet_id],
                on_mission=bool(self.orders),
                repair_limit=repair_limit)[0]
        # TODO: Allow to split fleet to send only damaged ships to repair
        ships_cur_health, ships_max_health = FleetUtilsAI.get_current_and_max_structure(
            fleet_id)
        return ships_cur_health < repair_limit * ships_max_health
Example #10
0
    def issue_order(self):
        if not super(OrderRepair, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            fo.issueAggressionOrder(fleet_id, False)
            start_id = FleetUtilsAI.get_fleet_system(fleet)
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(
                fleet_id, start_id, system_id)
            universe = fo.getUniverse()
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
                fleet_id, self.ORDER_NAME, universe.getSystem(dest_id),
                universe.getSystem(system_id))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (
                self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(
                    fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    foAI.foAIstate.needsEmergencyExploration.remove(system_id)
            self.order_issued = True
Example #11
0
    def issue_order(self):
        if not super(OrderResupply, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            # if self.order_type == AIFleetOrderType.ORDER_MOVE:
            #     dest_id = system_id
            # else:
            # if self.order_type == AIFleetOrderType.ORDER_REPAIR:
            #     fo.issueAggressionOrder(fleet_id, False)
            start_id = FleetUtilsAI.get_fleet_system(fleet)
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
                fleet_id, self.ORDER_NAME,
                PlanetUtilsAI.sys_name_ids([dest_id]),
                PlanetUtilsAI.sys_name_ids([system_id]))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    foAI.foAIstate.needsEmergencyExploration.remove(system_id)
            self.order_issued = True
Example #12
0
 def issue_order(self):
     if not super(OrderResupply, self).issue_order():
         return False
     fleet_id = self.fleet.id
     system_id = self.target.get_system().id
     fleet = self.fleet.get_object()
     aistate = get_aistate()
     if system_id == fleet.systemID:
         if aistate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
             if system_id in aistate.needsEmergencyExploration:
                 aistate.needsEmergencyExploration.remove(system_id)
         return True
     if system_id != fleet.nextSystemID:
         self.executed = False
         start_id = FleetUtilsAI.get_fleet_system(fleet)
         dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(
             fleet_id, start_id, system_id)
         universe = fo.getUniverse()
         debug(
             "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s"
             % (fleet_id, self.ORDER_NAME, universe.getSystem(dest_id),
                universe.getSystem(system_id)))
         fo.issueFleetMoveOrder(fleet_id, dest_id)
         debug("Order issued: %s fleet: %s target: %s" %
               (self.ORDER_NAME, self.fleet, self.target))
     return True
    def issue_order(self):
        if not super(OrderRepair, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            fo.issueAggressionOrder(fleet_id, False)
            start_id = [fleet.systemID,
                        fleet.nextSystemID][fleet.systemID == INVALID_ID]
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(
                fleet_id, start_id, system_id)
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
                fleet_id, self.ORDER_NAME, PlanetUtilsAI.sys_name_ids(
                    [dest_id]), PlanetUtilsAI.sys_name_ids([system_id]))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (
                self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(
                    fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    del foAI.foAIstate.needsEmergencyExploration[
                        foAI.foAIstate.needsEmergencyExploration.index(
                            system_id)]
            self.order_issued = True
Example #14
0
    def issue_order(self):
        if not super(OrderResupply, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            # if self.order_type == AIFleetOrderType.ORDER_MOVE:
            #     dest_id = system_id
            # else:
            # if self.order_type == AIFleetOrderType.ORDER_REPAIR:
            #     fo.issueAggressionOrder(fleet_id, False)
            start_id = FleetUtilsAI.get_fleet_system(fleet)
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
                fleet_id, self.ORDER_NAME,
                PlanetUtilsAI.sys_name_ids([dest_id]),
                PlanetUtilsAI.sys_name_ids([system_id]))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    foAI.foAIstate.needsEmergencyExploration.remove(system_id)
            self.order_issued = True
Example #15
0
def assignScoutsToExploreSystems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capitalSysID = PlanetUtilsAI.getCapitalSysID()
    # order fleets to explore
    #explorableSystemIDs = foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    explorableSystemIDs =  list(borderUnexploredSystemIDs)
    if not explorableSystemIDs or (capitalSysID == -1):
        return
    expSystemsByDist = sorted(  map( lambda x: ( universe.linearDistance(capitalSysID, x),  x) ,  explorableSystemIDs ) )
    print "Exploration system considering following system-distance pairs:\n %s"%("[ "+ ",  ".join(["%3d : %5.1f"%(sys, dist) for dist, sys in expSystemsByDist]) +" ]")
    exploreList = [sysID for dist, sysID in expSystemsByDist ]

    alreadyCovered,  availableScouts  = getCurrentExplorationInfo()


    print "explorable sys IDs: %s"%exploreList
    print "already targeted: %s"%alreadyCovered
    if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
        foAI.foAIstate.needsEmergencyExploration=[]
    needsCoverage= foAI.foAIstate.needsEmergencyExploration + [sysID for sysID in exploreList if sysID not in  alreadyCovered ] # emergency coverage cane be due to invasion detection trouble, etc.
    print "needs coverage: %s"%needsCoverage
    print "available scouts & AIstate locs: %s"%(map( lambda x: (x,  foAI.foAIstate.fleetStatus.get(x, {}).get('sysID', -1)),    availableScouts) )
    print "available scouts & universe locs: %s"%(map( lambda x: (x,  universe.getFleet(x).systemID),  availableScouts) )
    if not needsCoverage or not availableScouts:
        return

    availableScouts = set(availableScouts)
    sentList=[]
    while (len(availableScouts) > 0 ) and ( len(needsCoverage) >0):
        thisSysID = needsCoverage.pop(0)
        if (foAI.foAIstate.systemStatus.setdefault(thisSysID, {}).setdefault('monsterThreat', 0) > 2000*(foAI.foAIstate.aggression) ) or (fo.currentTurn() <20  and foAI.foAIstate.systemStatus[thisSysID]['monsterThreat'] > 200):
            print "Skipping exploration of system %d due to Big Monster,  threat %d"%(thisSysID,  foAI.foAIstate.systemStatus[thisSysID]['monsterThreat'])
            continue
        foundFleets=[]
        thisFleetList = FleetUtilsAI.getFleetsForMission(nships=1,  targetStats={},  minStats={},  curStats={},  species="",  systemsToCheck=[thisSysID],  systemsChecked=[],
                                                     fleetPoolSet = availableScouts,   fleetList=foundFleets,  verbose=False)
        if thisFleetList==[]:
            print "seem to have run out of scouts while trying to cover sysID %d"%thisSysID
            break #must have ran out of scouts
        fleetID = thisFleetList[0]
        aiFleetMission = foAI.foAIstate.getAIFleetMission( fleetID )
        aiTarget = AITarget.AITarget(AITargetType.TARGET_SYSTEM, thisSysID )
        if len(MoveUtilsAI.canTravelToSystemAndReturnToResupply(fleetID, aiFleetMission.getLocationAITarget(), aiTarget, fo.empireID())) > 0:
            aiFleetMission.addAITarget(AIFleetMissionType.FLEET_MISSION_EXPLORATION, aiTarget)
            sentList.append(thisSysID)
        else: #system too far out, skip it, but can add scout back to available pool
            print "sysID %d too far out for fleet ( ID %d ) to readch"%(thisSysID,  fleetID)
            availableScouts.update(thisFleetList)
    print "sent scouting fleets to sysIDs : %s"%sentList
    return
    # pylint: disable=pointless-string-statement
    """
Example #16
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    #explorable_system_ids = foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    explorable_system_ids = list(borderUnexploredSystemIDs)
    if not explorable_system_ids or (capital_sys_id == -1):
        return
    exp_systems_by_dist = sorted(map(lambda x: (universe.linearDistance(capital_sys_id, x), x), explorable_system_ids))
    print "Exploration system considering following system-distance pairs:\n %s"%("[ "+ ", ".join(["%3d : %5.1f"%(sys, dist) for dist, sys in exp_systems_by_dist]) +" ]")
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist ]

    already_covered, available_scouts = get_current_exploration_info()

    print "explorable sys IDs: %s"%explore_list
    print "already targeted: %s"%already_covered
    if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
        foAI.foAIstate.needsEmergencyExploration = []
    needs_coverage = foAI.foAIstate.needsEmergencyExploration + [sys_id for sys_id in explore_list if sys_id not in already_covered ] # emergency coverage cane be due to invasion detection trouble, etc.
    print "needs coverage: %s"%needs_coverage

    print "available scouts & AIstate locs: %s" % (map(lambda x: (x, foAI.foAIstate.fleetStatus.get(x, {}).get('sysID', -1)), available_scouts) )
    print "available scouts & universe locs: %s" % (map(lambda x: (x, universe.getFleet(x).systemID), available_scouts))
    if not needs_coverage or not available_scouts:
        return

    available_scouts = set(available_scouts)
    sent_list = []
    while (len(available_scouts) > 0 ) and ( len(needs_coverage) > 0):
        this_sys_id = needs_coverage.pop(0)
        if (foAI.foAIstate.systemStatus.setdefault(this_sys_id, {}).setdefault('monsterThreat', 0) > 2000* foAI.foAIstate.aggression ) or (fo.currentTurn() <20 and foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'] > 200):
            print "Skipping exploration of system %d due to Big Monster, threat %d"%(this_sys_id, foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'])
            continue
        found_fleets=[]
        this_fleet_list = FleetUtilsAI.get_fleets_for_mission(nships=1, target_stats={}, min_stats={}, cur_stats={}, species="", systems_to_check=[this_sys_id], systems_checked=[],
                                                     fleet_pool_set= available_scouts, fleet_list=found_fleets, verbose=False)
        if not this_fleet_list:
            print "seem to have run out of scouts while trying to cover sys_id %d"%this_sys_id
            break #must have ran out of scouts
        fleet_id = this_fleet_list[0]
        fleet_mission = foAI.foAIstate.get_fleet_mission( fleet_id )
        target = AITarget.AITarget(AITargetType.TARGET_SYSTEM, this_sys_id )
        if len(MoveUtilsAI.can_travel_to_system_and_return_to_resupply(fleet_id, fleet_mission.get_location_target(), target)) > 0:
            fleet_mission.add_target(AIFleetMissionType.FLEET_MISSION_EXPLORATION, target)
            sent_list.append(this_sys_id)
        else: #system too far out, skip it, but can add scout back to available pool
            print "sys_id %d too far out for fleet ( ID %d ) to readch"%(this_sys_id, fleet_id)
            available_scouts.update(this_fleet_list)
    print "sent scouting fleets to sysIDs : %s"%sent_list
    return
    # pylint: disable=pointless-string-statement
    """
Example #17
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    #explorable_system_ids = foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    explorable_system_ids = list(borderUnexploredSystemIDs)
    if not explorable_system_ids or (capital_sys_id == -1):
        return
    exp_systems_by_dist = sorted(map(lambda x: (universe.linearDistance(capital_sys_id, x), x), explorable_system_ids))
    print "Exploration system considering following system-distance pairs:\n %s" % ("[ " + ", ".join(["%3d : %5.1f" % (sys, dist) for dist, sys in exp_systems_by_dist]) + " ]")
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist]

    already_covered, available_scouts = get_current_exploration_info()

    print "explorable sys IDs: %s" % explore_list
    print "already targeted: %s" % already_covered
    if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
        foAI.foAIstate.needsEmergencyExploration = []
    needs_coverage = foAI.foAIstate.needsEmergencyExploration + [sys_id for sys_id in explore_list if sys_id not in already_covered]  # emergency coverage cane be due to invasion detection trouble, etc.
    print "needs coverage: %s" % needs_coverage

    print "available scouts & AIstate locs: %s" % (map(lambda x: (x, foAI.foAIstate.fleetStatus.get(x, {}).get('sysID', -1)), available_scouts))
    print "available scouts & universe locs: %s" % (map(lambda x: (x, universe.getFleet(x).systemID), available_scouts))
    if not needs_coverage or not available_scouts:
        return

    available_scouts = set(available_scouts)
    sent_list = []
    while (len(available_scouts) > 0) and (len(needs_coverage) > 0):
        this_sys_id = needs_coverage.pop(0)
        if (foAI.foAIstate.systemStatus.setdefault(this_sys_id, {}).setdefault('monsterThreat', 0) > 2000 * foAI.foAIstate.aggression) or (fo.currentTurn() < 20 and foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'] > 200):
            print "Skipping exploration of system %d due to Big Monster, threat %d" % (this_sys_id, foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'])
            continue
        found_fleets = []
        this_fleet_list = FleetUtilsAI.get_fleets_for_mission(nships=1, target_stats={}, min_stats={}, cur_stats={}, species="", systems_to_check=[this_sys_id], systems_checked=[],
                                                     fleet_pool_set=available_scouts, fleet_list=found_fleets, verbose=False)
        if not this_fleet_list:
            print "seem to have run out of scouts while trying to cover sys_id %d" % this_sys_id
            break  # must have ran out of scouts
        fleet_id = this_fleet_list[0]
        fleet_mission = foAI.foAIstate.get_fleet_mission(fleet_id)
        target = AITarget.AITarget(TargetType.TARGET_SYSTEM, this_sys_id)
        if len(MoveUtilsAI.can_travel_to_system_and_return_to_resupply(fleet_id, fleet_mission.get_location_target(), target)) > 0:
            fleet_mission.add_target(AIFleetMissionType.FLEET_MISSION_EXPLORATION, target)
            sent_list.append(this_sys_id)
        else:  # system too far out, skip it, but can add scout back to available pool
            print "sys_id %d too far out for fleet ( ID %d ) to reach" % (this_sys_id, fleet_id)
            available_scouts.update(this_fleet_list)
    print "sent scouting fleets to sysIDs : %s" % sent_list
    return
    # pylint: disable=pointless-string-statement
    """
Example #18
0
    def generateAIFleetOrders(self):
        "generates AIFleetOrders from fleets targets to accomplish"

        # TODO: priority
        self.clearAIFleetOrders()
        # for some targets fleet has to visit systems and therefore fleet visit them
        systemAITargets = self.__getRequiredToVisitSystemAITargets()
        aiFleetOrdersToVisitSystems = MoveUtilsAI.getAIFleetOrdersFromSystemAITargets(self.getAITarget(), systemAITargets)

        # if fleet is in some system = fleet.systemID >=0, then also generate system AIFleetOrders
        universe = fo.getUniverse()
        fleet = universe.getFleet(self.getAITargetID())
        systemID = fleet.systemID
        if systemID >= 0:
            # system in where fleet is
            systemAITarget = AITarget.AITarget(AITargetType.TARGET_SYSTEM, systemID)
            # if mission aiTarget has required system where fleet is, then generate aiFleetOrder from this aiTarget 
            aiMissionTypes = self.getAIMissionTypes()
            # for all targets in all mission types get required systems to visit 
            for aiFleetMissionType in aiMissionTypes:
                aiTargets = self.getAITargets(aiFleetMissionType)
                for aiTarget in aiTargets:
                    if systemAITarget in aiTarget.getRequiredSystemAITargets():
                        # from target required to visit get fleet orders to accomplish target
                        aiFleetOrder = self.__getAIFleetOrderFromAITarget(aiFleetMissionType, aiTarget)
                        self.appendAIFleetOrder(aiFleetOrder)

        for aiFleetOrder in aiFleetOrdersToVisitSystems:
            self.appendAIFleetOrder(aiFleetOrder)

        # if fleet don't have any mission, then resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
        if (not self.hasAnyAIMissionTypes()) and not(self.getLocationAITarget().getTargetID() in fleetSupplyableSystemIDs):
            resupplyAIFleetOrder = MoveUtilsAI.getResupplyAIFleetOrder(self.getAITarget(), self.getLocationAITarget())
            if resupplyAIFleetOrder.isValid():
                self.appendAIFleetOrder(resupplyAIFleetOrder)
Example #19
0
 def issue_order(self):
     if not super(OrderResupply, self).issue_order():
         return False
     fleet_id = self.fleet.id
     system_id = self.target.get_system().id
     fleet = self.fleet.get_object()
     if system_id == fleet.systemID:
         if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
             if system_id in foAI.foAIstate.needsEmergencyExploration:
                 foAI.foAIstate.needsEmergencyExploration.remove(system_id)
         return True
     if system_id != fleet.nextSystemID:
         self.executed = False
         start_id = FleetUtilsAI.get_fleet_system(fleet)
         dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
         universe = fo.getUniverse()
         print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
             fleet_id, self.ORDER_NAME, universe.getSystem(dest_id), universe.getSystem(system_id))
         fo.issueFleetMoveOrder(fleet_id, dest_id)
         print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)
     return True
Example #20
0
    def issue_order(self):
        if not super(OrderRepair, self).issue_order():
            return
        fleet_id = self.fleet.id
        system_id = self.target.get_system().id
        fleet = self.fleet.get_object()
        if system_id not in [fleet.systemID, fleet.nextSystemID]:
            fo.issueAggressionOrder(fleet_id, False)
            start_id = [fleet.systemID, fleet.nextSystemID][fleet.systemID == INVALID_ID]
            dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
            print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (fleet_id, self.ORDER_NAME,
                                                                                                  PlanetUtilsAI.sys_name_ids([dest_id]),
                                                                                                  PlanetUtilsAI.sys_name_ids([system_id]))
            fo.issueFleetMoveOrder(fleet_id, dest_id)
            print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)

        if system_id == fleet.systemID:
            if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
                if system_id in foAI.foAIstate.needsEmergencyExploration:
                    del foAI.foAIstate.needsEmergencyExploration[foAI.foAIstate.needsEmergencyExploration.index(system_id)]
            self.order_issued = True
Example #21
0
 def issue_order(self):
     if not super(OrderRepair, self).issue_order():
         return False
     fleet_id = self.fleet.id
     system_id = self.target.get_system().id
     fleet = self.fleet.get_object()  # type: fo.fleet
     if system_id == fleet.systemID:
         if foAI.foAIstate.get_fleet_role(fleet_id) == MissionType.EXPLORATION:
             if system_id in foAI.foAIstate.needsEmergencyExploration:
                 foAI.foAIstate.needsEmergencyExploration.remove(system_id)
     elif system_id != fleet.nextSystemID:
         fo.issueAggressionOrder(fleet_id, False)
         start_id = FleetUtilsAI.get_fleet_system(fleet)
         dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
         universe = fo.getUniverse()
         print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (
             fleet_id, self.ORDER_NAME, universe.getSystem(dest_id), universe.getSystem(system_id))
         fo.issueFleetMoveOrder(fleet_id, dest_id)
         print "Order issued: %s fleet: %s target: %s" % (self.ORDER_NAME, self.fleet, self.target)
     ships_cur_health, ships_max_health = FleetUtilsAI.get_current_and_max_structure(fleet_id)
     self.executed = (ships_cur_health == ships_max_health)
     return True
Example #22
0
def assignScoutsToExploreSystems():
    # TODO: use Graph Theory to explore closest systems

    fleetIDs = FleetUtilsAI.getEmpireFleetIDsByRole(AIFleetMissionType.FLEET_MISSION_EXPLORATION)

    # order fleets to explore
    explorableSystemIDs = foAI.foAIstate.getExplorableSystems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    for fleetID in fleetIDs:
        # if fleet already has a mission, continue
        aiFleetMission = foAI.foAIstate.getAIFleetMission(fleetID)
        if len(aiFleetMission.getAIMissionTypes()) > 0:
            continue

        # else send fleet to a system
        for systemID in explorableSystemIDs:
            # if system is already being explored, continue
            aiTarget = AITarget.AITarget(AITargetType.TARGET_SYSTEM, systemID)
            if foAI.foAIstate.hasAITarget(AIFleetMissionType.FLEET_MISSION_EXPLORATION, aiTarget):
                continue

            # add exploration mission to fleet with target unexplored system and this system is in range
            if len(MoveUtilsAI.canTravelToSystemAndReturnToResupply(fleetID, aiFleetMission.getLocationAITarget(), aiTarget, fo.empireID())) > 0:
                aiFleetMission.addAITarget(AIFleetMissionType.FLEET_MISSION_EXPLORATION, aiTarget)
                break
Example #23
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    # explorable_system_ids = foAI.foAIstate.get_explorable_systems(AIExplorableSystemType.EXPLORABLE_SYSTEM_UNEXPLORED)
    explorable_system_ids = list(borderUnexploredSystemIDs)
    if not explorable_system_ids or (capital_sys_id == -1):
        return
    exp_systems_by_dist = sorted(map(lambda x: (universe.linearDistance(capital_sys_id, x), x), explorable_system_ids))
    print "Exploration system considering following system-distance pairs:\n %s" % (
        "[ " + ", ".join(["%3d : %5.1f" % (sys, dist) for dist, sys in exp_systems_by_dist]) + " ]"
    )
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist]

    already_covered, available_scouts = get_current_exploration_info()

    print "explorable sys IDs: %s" % explore_list
    print "already targeted: %s" % already_covered
    if "needsEmergencyExploration" not in dir(foAI.foAIstate):
        foAI.foAIstate.needsEmergencyExploration = []
    needs_vis = foAI.foAIstate.misc.setdefault("needs_vis", [])
    check_list = foAI.foAIstate.needsEmergencyExploration + needs_vis + explore_list
    needs_coverage = [
        sys_id for sys_id in check_list if sys_id not in already_covered
    ]  # emergency coverage cane be due to invasion detection trouble, etc.
    print "needs coverage: %s" % needs_coverage

    print "available scouts & AIstate locs: %s" % (
        map(lambda x: (x, foAI.foAIstate.fleetStatus.get(x, {}).get("sysID", -1)), available_scouts)
    )
    print "available scouts & universe locs: %s" % (map(lambda x: (x, universe.getFleet(x).systemID), available_scouts))
    if not needs_coverage or not available_scouts:
        return

    available_scouts = set(available_scouts)
    sent_list = []
    while (len(available_scouts) > 0) and (len(needs_coverage) > 0):
        this_sys_id = needs_coverage.pop(0)
        sys_status = foAI.foAIstate.systemStatus.setdefault(this_sys_id, {})
        if this_sys_id not in explore_list:  # doesn't necessarily need direct visit
            if universe.getVisibility(this_sys_id, fo.empireID()) >= fo.visibility.partial:
                # already got visibility; remove from visit lists and skip
                if this_sys_id in needs_vis:
                    del needs_vis[needs_vis.index(this_sys_id)]
                if this_sys_id in foAI.foAIstate.needsEmergencyExploration:
                    del foAI.foAIstate.needsEmergencyExploration[
                        foAI.foAIstate.needsEmergencyExploration.index(this_sys_id)
                    ]
                print "sys id %d already currently visible; skipping exploration" % this_sys_id
                continue
        # TODO: if blocked byu monster, try to find nearby sys from which to see this sys
        if (sys_status.setdefault("monsterThreat", 0) > 2000 * foAI.foAIstate.aggression) or (
            fo.currentTurn() < 20 and foAI.foAIstate.systemStatus[this_sys_id]["monsterThreat"] > 200
        ):
            print "Skipping exploration of system %d due to Big Monster, threat %d" % (
                this_sys_id,
                foAI.foAIstate.systemStatus[this_sys_id]["monsterThreat"],
            )
            continue
        found_fleets = []
        this_fleet_list = FleetUtilsAI.get_fleets_for_mission(
            nships=1,
            target_stats={},
            min_stats={},
            cur_stats={},
            species="",
            systems_to_check=[this_sys_id],
            systems_checked=[],
            fleet_pool_set=available_scouts,
            fleet_list=found_fleets,
            verbose=False,
        )
        if not this_fleet_list:
            print "seem to have run out of scouts while trying to cover sys_id %d" % this_sys_id
            break  # must have ran out of scouts
        fleet_id = this_fleet_list[0]
        fleet_mission = foAI.foAIstate.get_fleet_mission(fleet_id)
        target = universe_object.System(this_sys_id)
        if (
            len(
                MoveUtilsAI.can_travel_to_system_and_return_to_resupply(
                    fleet_id, fleet_mission.get_location_target(), target
                )
            )
            > 0
        ):
            fleet_mission.add_target(AIFleetMissionType.FLEET_MISSION_EXPLORATION, target)
            sent_list.append(this_sys_id)
        else:  # system too far out, skip it, but can add scout back to available pool
            print "sys_id %d too far out for fleet ( ID %d ) to reach" % (this_sys_id, fleet_id)
            available_scouts.update(this_fleet_list)
    print "sent scouting fleets to sysIDs : %s" % sent_list
    return
    # pylint: disable=pointless-string-statement
    """
Example #24
0
def get_fleets_for_mission(target_stats, min_stats, cur_stats, starting_system,
                           fleet_pool_set, fleet_list, species=""):
    """Get fleets for a mission.

    Implements breadth-first search through systems starting at the **starting_sytem**.
    In each system, local fleets are checked if they are in the allowed **fleet_pool_set** and suitable for the mission.
    If so, they are added to the **fleet_list** and **cur_stats** is updated with the currently selected fleet summary.
    The search continues until the requirements defined in **target_stats** are met or there are no more systems/fleets.
    In that case, if the **min_stats** are covered, the **fleet_list** is returned anyway.
    Otherwise, an empty list is returned by the function, in which case the caller can make an evaluation of
    an emergency use of the found fleets in fleet_list; if not to be used they should be added back to the main pool.

    :param target_stats: stats the fleet should ideally meet
    :type target_stats: dict
    :param min_stats: minimum stats the final fleet must meet to be accepted
    :type min_stats: dict
    :param cur_stats: (**mutated**) stat summary of selected fleets
    :type cur_stats: dict
    :param starting_system: system_id where breadth-first-search is centered
    :type starting_system: int
    :param fleet_pool_set: (**mutated**) fleets allowed to be selected. Split fleed_ids are added, used ones removed.
    :type: fleet_pool_set: set[int]
    :param fleet_list: (**mutated**) fleets that are selected for the mission. Gets filled during the call.
    :type fleet_list: list[int]
    :param species: species for colonization mission
    :type species: str
    :return: List of selected fleet_ids or empty list if couldn't meet minimum requirements.
    :rtype: list[int]
    """
    universe = fo.getUniverse()
    colonization_roles = (ShipRoleType.CIVILIAN_COLONISATION, ShipRoleType.BASE_COLONISATION)
    systems_enqueued = [starting_system]
    systems_visited = []
    # loop over systems in a breadth-first-search trying to find nearby suitable ships in fleet_pool_set
    aistate = get_aistate()
    while systems_enqueued and fleet_pool_set:
        this_system_id = systems_enqueued.pop(0)
        this_system_obj = universe_object.System(this_system_id)
        systems_visited.append(this_system_id)
        accessible_fleets = aistate.systemStatus.get(this_system_id, {}).get('myFleetsAccessible', [])
        fleets_here = [fid for fid in accessible_fleets if fid in fleet_pool_set]
        # loop over all fleets in the system, split them if possible and select suitable ships
        while fleets_here:
            fleet_id = fleets_here.pop(0)
            fleet = universe.getFleet(fleet_id)
            if not fleet:  # TODO should be checked before passed to the function
                fleet_pool_set.remove(fleet_id)
                continue
            # try splitting fleet
            if len(list(fleet.shipIDs)) > 1:
                new_fleets = split_fleet(fleet_id)
                fleet_pool_set.update(new_fleets)
                fleets_here.extend(new_fleets)
            # check species for colonization missions
            if species:
                for ship_id in fleet.shipIDs:
                    ship = universe.getShip(ship_id)
                    if (ship and aistate.get_ship_role(ship.design.id) in colonization_roles and
                            species == ship.speciesName):
                        break
                else:  # no suitable species found
                    continue
            # check troop capacity for invasion missions
            troop_capacity = 0
            if 'troopCapacity' in target_stats:
                troop_capacity = count_troops_in_fleet(fleet_id)
                if troop_capacity <= 0:
                    continue
                if 'target_system' in target_stats:
                    if not MoveUtilsAI.can_travel_to_system(fleet_id, this_system_obj, target_stats['target_system']):
                        continue

            # check if we need additional rating vs planets
            this_rating_vs_planets = 0
            if 'ratingVsPlanets' in target_stats:
                this_rating_vs_planets = aistate.get_rating(fleet_id, against_planets=True)
                if this_rating_vs_planets <= 0 and cur_stats.get('rating', 0) >= target_stats.get('rating', 0):
                    # we already have enough general rating, so do not add any more warships useless against planets
                    continue

            # all checks passed, add ship to selected fleets and update the stats
            try:
                fleet_pool_set.remove(fleet_id)
            except KeyError:
                error("After having split a fleet, the original fleet apparently no longer exists.", exc_info=True)
                continue
            fleet_list.append(fleet_id)

            this_rating = aistate.get_rating(fleet_id)
            cur_stats['rating'] = CombatRatingsAI.combine_ratings(cur_stats.get('rating', 0), this_rating)
            if 'ratingVsPlanets' in target_stats:
                cur_stats['ratingVsPlanets'] = CombatRatingsAI.combine_ratings(cur_stats.get('ratingVsPlanets', 0),
                                                                               this_rating_vs_planets)
            if 'troopCapacity' in target_stats:
                cur_stats['troopCapacity'] = cur_stats.get('troopCapacity', 0) + troop_capacity
            # if we already meet the requirements, we can stop looking for more ships
            if (sum(len(universe.getFleet(fid).shipIDs) for fid in fleet_list) >= 1) \
                    and stats_meet_reqs(cur_stats, target_stats):
                return fleet_list

        # finished system without meeting requirements. Add neighboring systems to search queue.
        for neighbor_id in universe.getImmediateNeighbors(this_system_id, fo.empireID()):
            if all((
                    neighbor_id not in systems_visited,
                    neighbor_id not in systems_enqueued,
                    neighbor_id in aistate.exploredSystemIDs
            )):
                systems_enqueued.append(neighbor_id)
    # we ran out of systems or fleets to check but did not meet requirements yet.
    if stats_meet_reqs(cur_stats, min_stats) and any(universe.getFleet(fid).shipIDs for fid in fleet_list):
        return fleet_list
    else:
        return []
Example #25
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.target_id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (
                fleet_id in universe.destroyedObjectIDs(fo.empireID())
        ):  # fleet was probably merged into another or was destroyed
            foAI.foAIstate.delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission, then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        #if (not self.hasAnyAIMissionTypes()):
        ntargets = 0
        for mission_type in self.get_mission_types():
            ntargets += len(self.get_targets(mission_type))
        if not ntargets and (system_id
                             not in set(AIstate.colonyTargetedSystemIDs +
                                        AIstate.outpostTargetedSystemIDs +
                                        AIstate.invasionTargetedSystemIDs +
                                        AIstate.blockadeTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(
                    self.target, start_sys_id)
                if repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            if self.get_location_target(
            ).target_id not in fleet_supplyable_system_ids:
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(
                    self.target, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        system_targets_required_to_visit = []
        for mission_type in self.get_mission_types():
            for aiTarget in self.get_targets(mission_type):
                system_targets_required_to_visit.extend(
                    aiTarget.get_required_system_ai_targets())

        orders_to_visit_systems = MoveUtilsAI.get_fleet_orders_from_system_targets(
            self.target, system_targets_required_to_visit)
        #TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
        #print "----------------------------------------"
        #print "*+*+ fleet %d : has fleet action system targets: %s"%(fleet_id, [str(obj) for obj in system_targets_required_to_visit])
        #print "----------"
        #print "*+*+ fleet %d: has movement orders: %s"%(fleet_id, [str(obj) for obj in orders_to_visit_systems])

        for fleet_order in orders_to_visit_systems:
            self.orders.append(fleet_order)

        # if fleet is in some system = fleet.system_id >=0, then also generate system AIFleetOrders
        if system_id >= 0:
            # system in where fleet is
            system_target = AITarget(EnumsAI.TargetType.TARGET_SYSTEM,
                                     system_id)
            # if mission aiTarget has required system where fleet is, then generate fleet_order from this aiTarget
            # for all targets in all mission types get required systems to visit
            for mission_type in self.get_mission_types():
                tragets = self.get_targets(mission_type)
                for target in tragets:
                    if system_target in target.get_required_system_ai_targets(
                    ):
                        # from target required to visit get fleet orders to accomplish target
                        fleet_order = self._get_fleet_order_from_target(
                            mission_type, target)
                        self.orders.append(fleet_order)
Example #26
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    if not border_unexplored_system_ids or (capital_sys_id == INVALID_ID):
        return
    exp_systems_by_dist = sorted((universe.linearDistance(capital_sys_id, x), x) for x in border_unexplored_system_ids)
    debug("Exploration system considering following system-distance pairs:\n  %s" % (
        "\n  ".join("%3d: %5.1f" % (sys_id, dist) for (dist, sys_id) in exp_systems_by_dist)))
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist]

    already_covered, available_scouts = get_current_exploration_info()

    debug("Explorable system IDs: %s" % explore_list)
    debug("Already targeted: %s" % already_covered)
    aistate = get_aistate()
    needs_vis = aistate.misc.setdefault('needs_vis', [])
    check_list = aistate.needsEmergencyExploration + needs_vis + explore_list
    if INVALID_ID in check_list:  # shouldn't normally happen, unless due to bug elsewhere
        for sys_list, name in [(aistate.needsEmergencyExploration, "aistate.needsEmergencyExploration"),
                               (needs_vis, "needs_vis"), (explore_list, "explore_list")]:
            if INVALID_ID in sys_list:
                error("INVALID_ID found in " + name, exc_info=True)
    # emergency coverage can be due to invasion detection trouble, etc.
    debug("Check list: %s" % check_list)
    needs_coverage = [sys_id for sys_id in check_list if sys_id not in already_covered and sys_id != INVALID_ID]
    debug("Needs coverage: %s" % needs_coverage)

    debug("Available scouts & AIstate locs: %s" % [(x, aistate.fleetStatus.get(x, {}).get('sysID', INVALID_ID))
                                                   for x in available_scouts])
    debug("Available scouts & universe locs: %s" % [(x, universe.getFleet(x).systemID) for x in available_scouts])
    if not needs_coverage or not available_scouts:
        return

    # clean up targets which can not or don't need to be scouted
    for sys_id in list(needs_coverage):
        if sys_id not in explore_list:  # doesn't necessarily need direct visit
            if universe.getVisibility(sys_id, fo.empireID()) >= fo.visibility.partial:
                # already got visibility; remove from visit lists and skip
                if sys_id in needs_vis:
                    del needs_vis[needs_vis.index(sys_id)]
                if sys_id in aistate.needsEmergencyExploration:
                    del aistate.needsEmergencyExploration[
                        aistate.needsEmergencyExploration.index(sys_id)]
                debug("system id %d already currently visible; skipping exploration" % sys_id)
                needs_coverage.remove(sys_id)
                continue

        # skip systems threatened by monsters
        sys_status = aistate.systemStatus.setdefault(sys_id, {})
        if (not aistate.character.may_explore_system(sys_status.setdefault('monsterThreat', 0)) or (
                fo.currentTurn() < 20 and aistate.systemStatus[sys_id]['monsterThreat'] > 0)):
            debug("Skipping exploration of system %d due to Big Monster, threat %d" % (
                sys_id, aistate.systemStatus[sys_id]['monsterThreat']))
            needs_coverage.remove(sys_id)
            continue

    # find the jump distance for all possible scout-system pairings
    options = []
    available_scouts = set(available_scouts)
    for fleet_id in available_scouts:
        fleet_mission = aistate.get_fleet_mission(fleet_id)
        start = fleet_mission.get_location_target()
        for sys_id in needs_coverage:
            target = TargetSystem(sys_id)
            path = MoveUtilsAI.can_travel_to_system(fleet_id, start, target, ensure_return=True)
            if not path:
                continue
            num_jumps = len(path) - 1  # -1 as path contains the original system
            options.append((num_jumps, fleet_id, sys_id))

    # Apply a simple, greedy heuristic to match scouts to nearby systems:
    # Always choose the shortest possible path from the remaining scout-system pairing.
    # This is clearly not optimal in the general case but it works well enough for now.
    # TODO: Consider using a more sophisticated assignment algorithm
    options.sort()
    while options:
        debug("Remaining options: %s" % options)
        _, fleet_id, sys_id = options[0]
        fleet_mission = aistate.get_fleet_mission(fleet_id)
        target = TargetSystem(sys_id)
        info("Sending fleet %d to explore %s" % (fleet_id, target))
        fleet_mission.set_target(MissionType.EXPLORATION, target)
        options = [option for option in options if option[1] != fleet_id and option[2] != sys_id]
        available_scouts.remove(fleet_id)
        needs_coverage.remove(sys_id)

    debug("Exploration assignment finished.")
    debug("Unassigned scouts: %s" % available_scouts)
    debug("Unassigned exploration targets: %s" % needs_coverage)
Example #27
0
    def issueOrder(self,  considerMergers=False):
        global dumpTurn
        if not self.canIssueOrder(considerMergers=False):  #appears to be redundant with check in IAFleetMission?
            print "\tcan't issue %s"%self
        else:
            universe=fo.getUniverse()
            self.__setExecuted()
            # outpost
            if AIFleetOrderType.ORDER_OUTPOST == self.getAIFleetOrderType():
                planet=universe.getPlanet(self.getTargetAITarget().target_id)
                if not planet.unowned:
                    self.__setExecutionCompleted()
                    return
                shipID = None
                if AITargetType.TARGET_SHIP == self.getSourceAITarget().target_type:
                    shipID = self.getSourceAITarget().target_id
                elif AITargetType.TARGET_FLEET == self.getSourceAITarget().target_type:
                    fleetID = self.getSourceAITarget().target_id
                    shipID = FleetUtilsAI.getShipIDWithRole(fleetID, AIShipRoleType.SHIP_ROLE_CIVILIAN_OUTPOST)
                    if shipID is None:
                        shipID = FleetUtilsAI.getShipIDWithRole(fleetID, AIShipRoleType.SHIP_ROLE_BASE_OUTPOST)
                result=fo.issueColonizeOrder(shipID, self.getTargetAITarget().target_id)
                if result==0:
                    self.__executed = False
            # colonise
            elif AIFleetOrderType.ORDER_COLONISE == self.getAIFleetOrderType():
                shipID = None
                if AITargetType.TARGET_SHIP == self.getSourceAITarget().target_type:
                    shipID = self.getSourceAITarget().target_id
                elif AITargetType.TARGET_FLEET == self.getSourceAITarget().target_type:
                    fleetID = self.getSourceAITarget().target_id
                    shipID = FleetUtilsAI.getShipIDWithRole(fleetID, AIShipRoleType.SHIP_ROLE_CIVILIAN_COLONISATION)
                    if shipID is None:
                        shipID = FleetUtilsAI.getShipIDWithRole(fleetID, AIShipRoleType.SHIP_ROLE_BASE_COLONISATION)

                planetID = self.getTargetAITarget().target_id
                planet=universe.getPlanet(planetID)
                planetName = (planet and planet.name) or "apparently invisible"
                result = fo.issueColonizeOrder(shipID, planetID)
                print "Ordered colony ship ID %d to colonize %s, got result %d"%(shipID, planetName,  result)
                if result==0:
                    self.__executed = False
            # invade
            elif AIFleetOrderType.ORDER_INVADE == self.getAIFleetOrderType():
                result = False
                shipID = None
                planetID = self.getTargetAITarget().target_id
                planet=universe.getPlanet(planetID)
                planetName = (planet and planet.name) or "invisible"
                if AITargetType.TARGET_SHIP == self.getSourceAITarget().target_type:
                    shipID = self.getSourceAITarget().target_id
                elif AITargetType.TARGET_FLEET == self.getSourceAITarget().target_type:
                    fleetID = self.getSourceAITarget().target_id
                    fleet = fo.getUniverse().getFleet(fleetID)
                    for shipID in fleet.shipIDs:
                        ship = universe.getShip(shipID)
                        if (foAI.foAIstate.getShipRole(ship.design.id) in [AIShipRoleType.SHIP_ROLE_MILITARY_INVASION,  AIShipRoleType.SHIP_ROLE_BASE_INVASION]):
                            result = fo.issueInvadeOrder(shipID, planetID)  or  result #will track if at least one invasion troops successfully deployed
                            detailStr = ""
                            if result == 0:
                                pstealth = planet.currentMeterValue(fo.meterType.stealth)
                                pop = planet.currentMeterValue(fo.meterType.population)
                                shields = planet.currentMeterValue(fo.meterType.shield)
                                owner = planet.owner
                                detailStr= " -- planet has %.1f stealth, shields %.1f,  %.1f population and is owned by empire %d"%(pstealth,  shields,  pop,  owner)
                            print "Ordered troop ship ID %d to invade %s, got result %d"%(shipID, planetName,  result),  detailStr
                            if result == 0:
                                if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
                                    foAI.foAIstate.needsEmergencyExploration=[]
                                if  fleet.systemID not in foAI.foAIstate.needsEmergencyExploration:
                                    foAI.foAIstate.needsEmergencyExploration.append(fleet.systemID)
                                    print "Due to trouble invading,  adding system %d to Emergency Exploration List"%fleet.systemID
                                    self.__executed = False
                                if shields >0 and owner==-1 and dumpTurn<fo.currentTurn():
                                    dumpTurn=fo.currentTurn()
                                    print "Universe Dump to debug invasions:"
                                    universe.dump()
                                break
                if result:
                    print "Successfully ordered troop ship(s) to invade %s, with detail%s "%(planetName,  detailStr)
            # military
            elif AIFleetOrderType.ORDER_MILITARY == self.getAIFleetOrderType():
                shipID = None
                if AITargetType.TARGET_SHIP == self.getSourceAITarget().target_type:
                    shipID = self.getSourceAITarget().target_id
                elif AITargetType.TARGET_FLEET == self.getSourceAITarget().target_type:
                    fleetID = self.getSourceAITarget().target_id
                    shipID = FleetUtilsAI.getShipIDWithRole(fleetID, AIShipRoleType.SHIP_ROLE_MILITARY)
                #fo.issueFleetMoveOrder(fleetID, self.getTargetAITarget().target_id) #moving is already taken care of separately
                targetSysID = self.getTargetAITarget().target_id
                fleet = fo.getUniverse().getFleet(fleetID)
                systemStatus =  foAI.foAIstate.systemStatus.get(targetSysID,  {})
                if (fleet )and ( fleet.systemID==targetSysID ) and ((systemStatus.get('fleetThreat', 0) + systemStatus.get('planetThreat', 0)+ systemStatus.get('monsterThreat', 0))==0):
                    self.__setExecutionCompleted()

            # move or resupply
            elif self.getAIFleetOrderType() in [ AIFleetOrderType.ORDER_MOVE,  AIFleetOrderType.ORDER_REPAIR, AIFleetOrderType.ORDER_RESUPPLY]:
                fleetID = self.getSourceAITarget().target_id
                system_id = self.getTargetAITarget().target_id
                fleet = fo.getUniverse().getFleet(fleetID)
                if  system_id not in [fleet.systemID,  fleet.nextSystemID] :
                    if self.getAIFleetOrderType() == AIFleetOrderType.ORDER_MOVE:
                        dest_id = system_id
                    else:
                        if self.getAIFleetOrderType() == AIFleetOrderType.ORDER_REPAIR:
                            fo.issueAggressionOrder(fleetID,  False)
                        start_id = [fleet.systemID,  fleet.nextSystemID][ fleet.systemID == -1 ]
                        dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleetID,  start_id,  system_id)
                        print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s"%(fleetID, AIFleetOrderTypeNames.name(self.getAIFleetOrderType()), 
                                                                                                            PlanetUtilsAI.sysNameIDs([dest_id]), 
                                                                                                            PlanetUtilsAI.sysNameIDs([system_id]))
                    fo.issueFleetMoveOrder(fleetID, dest_id)
                if system_id == fleet.systemID:
                    if    foAI.foAIstate.getFleetRole(fleetID) == AIFleetMissionType.FLEET_MISSION_EXPLORATION :
                        if system_id in foAI.foAIstate.needsEmergencyExploration:
                            del foAI.foAIstate.needsEmergencyExploration[ foAI.foAIstate.needsEmergencyExploration.index(system_id) ]
                    self.__setExecutionCompleted()

            # split fleet
            elif AIFleetOrderType.ORDER_SPLIT_FLEET == self.getAIFleetOrderType():
                fleetID = self.getSourceAITarget().target_id
                shipID = self.getTargetAITarget().target_id
                fleet = fo.getUniverse().getFleet(fleetID)
                if shipID in fleet.shipIDs:
                    fo.issueNewFleetOrder(str(shipID), shipID)
                self.__setExecutionCompleted()
            # attack
            elif (AIFleetOrderType.ORDER_ATTACK == self.getAIFleetOrderType()):
                fleetID = self.getSourceAITarget().target_id
                systemID = self.getTargetAITarget().get_required_system_ai_targets()[0].target_id

                fo.issueFleetMoveOrder(fleetID, systemID)
Example #28
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    if not border_unexplored_system_ids or (capital_sys_id == INVALID_ID):
        return
    exp_systems_by_dist = sorted(
        (universe.linearDistance(capital_sys_id, x), x)
        for x in border_unexplored_system_ids)
    debug(
        "Exploration system considering following system-distance pairs:\n  %s"
        % ("\n  ".join("%3d: %5.1f" % (sys_id, dist)
                       for (dist, sys_id) in exp_systems_by_dist)))
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist]

    already_covered, available_scouts = get_current_exploration_info()

    debug("Explorable system IDs: %s" % explore_list)
    debug("Already targeted: %s" % already_covered)
    aistate = get_aistate()
    needs_vis = aistate.misc.setdefault('needs_vis', [])
    check_list = aistate.needsEmergencyExploration + needs_vis + explore_list
    if INVALID_ID in check_list:  # shouldn't normally happen, unless due to bug elsewhere
        for sys_list, name in [(aistate.needsEmergencyExploration,
                                "aistate.needsEmergencyExploration"),
                               (needs_vis, "needs_vis"),
                               (explore_list, "explore_list")]:
            if INVALID_ID in sys_list:
                error("INVALID_ID found in " + name, exc_info=True)
    # emergency coverage can be due to invasion detection trouble, etc.
    debug("Check list: %s" % check_list)
    needs_coverage = [
        sys_id for sys_id in check_list
        if sys_id not in already_covered and sys_id != INVALID_ID
    ]
    debug("Needs coverage: %s" % needs_coverage)

    debug("Available scouts & AIstate locs: %s" %
          [(x, aistate.fleetStatus.get(x, {}).get('sysID', INVALID_ID))
           for x in available_scouts])
    debug("Available scouts & universe locs: %s" %
          [(x, universe.getFleet(x).systemID) for x in available_scouts])
    if not needs_coverage or not available_scouts:
        return

    # clean up targets which can not or don't need to be scouted
    for sys_id in list(needs_coverage):
        if sys_id not in explore_list:  # doesn't necessarily need direct visit
            if universe.getVisibility(sys_id,
                                      fo.empireID()) >= fo.visibility.partial:
                # already got visibility; remove from visit lists and skip
                if sys_id in needs_vis:
                    del needs_vis[needs_vis.index(sys_id)]
                if sys_id in aistate.needsEmergencyExploration:
                    del aistate.needsEmergencyExploration[
                        aistate.needsEmergencyExploration.index(sys_id)]
                debug(
                    "system id %d already currently visible; skipping exploration"
                    % sys_id)
                needs_coverage.remove(sys_id)
                continue

        # skip systems threatened by monsters
        sys_status = aistate.systemStatus.setdefault(sys_id, {})
        if (not aistate.character.may_explore_system(
                sys_status.setdefault('monsterThreat', 0))
                or (fo.currentTurn() < 20
                    and aistate.systemStatus[sys_id]['monsterThreat'] > 0)):
            debug(
                "Skipping exploration of system %d due to Big Monster, threat %d"
                % (sys_id, aistate.systemStatus[sys_id]['monsterThreat']))
            needs_coverage.remove(sys_id)
            continue

    # find the jump distance for all possible scout-system pairings
    options = []
    available_scouts = set(available_scouts)
    for fleet_id in available_scouts:
        fleet_mission = aistate.get_fleet_mission(fleet_id)
        start = fleet_mission.get_location_target()
        for sys_id in needs_coverage:
            target = TargetSystem(sys_id)
            path = MoveUtilsAI.can_travel_to_system(fleet_id,
                                                    start,
                                                    target,
                                                    ensure_return=True)
            if not path:
                continue
            num_jumps = len(
                path) - 1  # -1 as path contains the original system
            options.append((num_jumps, fleet_id, sys_id))

    # Apply a simple, greedy heuristic to match scouts to nearby systems:
    # Always choose the shortest possible path from the remaining scout-system pairing.
    # This is clearly not optimal in the general case but it works well enough for now.
    # TODO: Consider using a more sophisticated assignment algorithm
    options.sort()
    while options:
        debug("Remaining options: %s" % options)
        _, fleet_id, sys_id = options[0]
        fleet_mission = aistate.get_fleet_mission(fleet_id)
        target = TargetSystem(sys_id)
        info("Sending fleet %d to explore %s" % (fleet_id, target))
        fleet_mission.set_target(MissionType.EXPLORATION, target)
        options = [
            option for option in options
            if option[1] != fleet_id and option[2] != sys_id
        ]
        available_scouts.remove(fleet_id)
        needs_coverage.remove(sys_id)

    debug("Exploration assignment finished.")
    debug("Unassigned scouts: %s" % available_scouts)
    debug("Unassigned exploration targets: %s" % needs_coverage)
Example #29
0
def get_fleets_for_mission(target_stats,
                           min_stats,
                           cur_stats,
                           starting_system,
                           fleet_pool_set,
                           fleet_list,
                           species="",
                           ensure_return=False):
    """Get fleets for a mission.

    Implements breadth-first search through systems starting at the **starting_sytem**.
    In each system, local fleets are checked if they are in the allowed **fleet_pool_set** and suitable for the mission.
    If so, they are added to the **fleet_list** and **cur_stats** is updated with the currently selected fleet summary.
    The search continues until the requirements defined in **target_stats** are met or there are no more systems/fleets.
    In that case, if the **min_stats** are covered, the **fleet_list** is returned anyway.
    Otherwise, an empty list is returned by the function, in which case the caller can make an evaluation of
    an emergency use of the found fleets in fleet_list; if not to be used they should be added back to the main pool.

    :param target_stats: stats the fleet should ideally meet
    :type target_stats: dict
    :param min_stats: minimum stats the final fleet must meet to be accepted
    :type min_stats: dict
    :param cur_stats: (**mutated**) stat summary of selected fleets
    :type cur_stats: dict
    :param starting_system: system_id where breadth-first-search is centered
    :type starting_system: int
    :param fleet_pool_set: (**mutated**) fleets allowed to be selected. Split fleed_ids are added, used ones removed.
    :type: fleet_pool_set: set[int]
    :param fleet_list: (**mutated**) fleets that are selected for the mission. Gets filled during the call.
    :type fleet_list: list[int]
    :param species: species for colonization mission
    :type species: str
    :param bool ensure_return: If true, fleet must have sufficient fuel to return into supply after mission
    :return: List of selected fleet_ids or empty list if couldn't meet minimum requirements.
    :rtype: list[int]
    """
    universe = fo.getUniverse()
    colonization_roles = (ShipRoleType.CIVILIAN_COLONISATION,
                          ShipRoleType.BASE_COLONISATION)
    systems_enqueued = [starting_system]
    systems_visited = []
    # loop over systems in a breadth-first-search trying to find nearby suitable ships in fleet_pool_set
    aistate = get_aistate()
    while systems_enqueued and fleet_pool_set:
        this_system_id = systems_enqueued.pop(0)
        this_system_obj = TargetSystem(this_system_id)
        systems_visited.append(this_system_id)
        accessible_fleets = aistate.systemStatus.get(this_system_id, {}).get(
            'myFleetsAccessible', [])
        fleets_here = [
            fid for fid in accessible_fleets if fid in fleet_pool_set
        ]
        # loop over all fleets in the system, split them if possible and select suitable ships
        while fleets_here:
            fleet_id = fleets_here.pop(0)
            fleet = universe.getFleet(fleet_id)
            if not fleet:  # TODO should be checked before passed to the function
                fleet_pool_set.remove(fleet_id)
                continue
            # try splitting fleet
            if fleet.numShips > 1:
                debug("Splitting candidate fleet to get ships for mission.")
                new_fleets = split_fleet(fleet_id)
                fleet_pool_set.update(new_fleets)
                fleets_here.extend(new_fleets)

            if ('target_system' in target_stats
                    and not MoveUtilsAI.can_travel_to_system(
                        fleet_id,
                        this_system_obj,
                        target_stats['target_system'],
                        ensure_return=ensure_return)):
                continue

            # check species for colonization missions
            if species:
                for ship_id in fleet.shipIDs:
                    ship = universe.getShip(ship_id)
                    if (ship and aistate.get_ship_role(
                            ship.design.id) in colonization_roles
                            and species == ship.speciesName):
                        break
                else:  # no suitable species found
                    continue
            # check troop capacity for invasion missions
            troop_capacity = 0
            if 'troopCapacity' in target_stats:
                troop_capacity = count_troops_in_fleet(fleet_id)
                if troop_capacity <= 0:
                    continue

            # check if we need additional rating vs planets
            this_rating_vs_planets = 0
            if 'ratingVsPlanets' in target_stats:
                this_rating_vs_planets = aistate.get_rating(
                    fleet_id, against_planets=True)
                if this_rating_vs_planets <= 0 and cur_stats.get(
                        'rating', 0) >= target_stats.get('rating', 0):
                    # we already have enough general rating, so do not add any more warships useless against planets
                    continue

            # all checks passed, add ship to selected fleets and update the stats
            try:
                fleet_pool_set.remove(fleet_id)
            except KeyError:
                error(
                    "After having split a fleet, the original fleet apparently no longer exists.",
                    exc_info=True)
                continue
            fleet_list.append(fleet_id)

            this_rating = aistate.get_rating(fleet_id)
            cur_stats['rating'] = CombatRatingsAI.combine_ratings(
                cur_stats.get('rating', 0), this_rating)
            if 'ratingVsPlanets' in target_stats:
                cur_stats['ratingVsPlanets'] = CombatRatingsAI.combine_ratings(
                    cur_stats.get('ratingVsPlanets', 0),
                    this_rating_vs_planets)
            if 'troopCapacity' in target_stats:
                cur_stats['troopCapacity'] = cur_stats.get('troopCapacity',
                                                           0) + troop_capacity
            # if we already meet the requirements, we can stop looking for more ships
            if (sum(len(universe.getFleet(fid).shipIDs) for fid in fleet_list) >= 1) \
                    and stats_meet_reqs(cur_stats, target_stats):
                return fleet_list

        # finished system without meeting requirements. Add neighboring systems to search queue.
        for neighbor_id in universe.getImmediateNeighbors(
                this_system_id, fo.empireID()):
            if all((neighbor_id not in systems_visited, neighbor_id
                    not in systems_enqueued, neighbor_id
                    in aistate.exploredSystemIDs)):
                systems_enqueued.append(neighbor_id)
    # we ran out of systems or fleets to check but did not meet requirements yet.
    if stats_meet_reqs(cur_stats, min_stats) and any(
            universe.getFleet(fid).shipIDs for fid in fleet_list):
        return fleet_list
    else:
        return []
Example #30
0
    def issue_order(self):
        global dumpTurn
        if not self.can_issue_order():  # appears to be redundant with check in IAFleetMission?
            print "\tcan't issue %s" % self
        else:
            universe = fo.getUniverse()
            self.executed = True
            # outpost
            if AIFleetOrderType.ORDER_OUTPOST == self.order_type:
                planet = universe.getPlanet(self.target.target_id)
                if not planet.unowned:
                    self.execution_completed = True
                    return
                fleet_id = self.fleet.target_id
                ship_id = FleetUtilsAI.get_ship_id_with_role(fleet_id, AIShipRoleType.SHIP_ROLE_CIVILIAN_OUTPOST)
                if ship_id is None:
                    ship_id = FleetUtilsAI.get_ship_id_with_role(fleet_id, AIShipRoleType.SHIP_ROLE_BASE_OUTPOST)
                result = fo.issueColonizeOrder(ship_id, self.target.target_id)
                if not result:
                    self.executed = False
            # colonise
            elif AIFleetOrderType.ORDER_COLONISE == self.order_type:
                fleet_id = self.fleet.target_id
                ship_id = FleetUtilsAI.get_ship_id_with_role(fleet_id, AIShipRoleType.SHIP_ROLE_CIVILIAN_COLONISATION)
                if ship_id is None:
                    ship_id = FleetUtilsAI.get_ship_id_with_role(fleet_id, AIShipRoleType.SHIP_ROLE_BASE_COLONISATION)

                planet_id = self.target.target_id
                planet = universe.getPlanet(planet_id)
                planet_name = planet and planet.name or "apparently invisible"
                result = fo.issueColonizeOrder(ship_id, planet_id)
                print "Ordered colony ship ID %d to colonize %s, got result %d" % (ship_id, planet_name, result)
                if not result:
                    self.executed = False
            # invade
            elif AIFleetOrderType.ORDER_INVADE == self.order_type:
                result = False
                planet_id = self.target.target_id
                planet = universe.getPlanet(planet_id)
                planet_name = planet and planet.name or "invisible"

                fleet_id = self.fleet.target_id
                fleet = fo.getUniverse().getFleet(fleet_id)
                detail_str = ""
                for ship_id in fleet.shipIDs:
                    ship = universe.getShip(ship_id)
                    if foAI.foAIstate.get_ship_role(ship.design.id) in [AIShipRoleType.SHIP_ROLE_MILITARY_INVASION, AIShipRoleType.SHIP_ROLE_BASE_INVASION]:
                        result = fo.issueInvadeOrder(ship_id, planet_id) or result  # will track if at least one invasion troops successfully deployed
                        shields = planet.currentMeterValue(fo.meterType.shield)
                        owner = planet.owner
                        if not result:
                            pstealth = planet.currentMeterValue(fo.meterType.stealth)
                            pop = planet.currentMeterValue(fo.meterType.population)
                            detail_str = " -- planet has %.1f stealth, shields %.1f, %.1f population and is owned by empire %d" % (pstealth, shields, pop, owner)
                        print "Ordered troop ship ID %d to invade %s, got result %d" % (ship_id, planet_name, result), detail_str
                        if not result:
                            if 'needsEmergencyExploration' not in dir(foAI.foAIstate):
                                foAI.foAIstate.needsEmergencyExploration = []
                            if fleet.systemID not in foAI.foAIstate.needsEmergencyExploration:
                                foAI.foAIstate.needsEmergencyExploration.append(fleet.systemID)
                                print "Due to trouble invading, adding system %d to Emergency Exploration List" % fleet.systemID
                                self.executed = False
                            if shields > 0 and owner == -1 and dumpTurn < fo.currentTurn():
                                dumpTurn = fo.currentTurn()
                                print "Universe Dump to debug invasions:"
                                universe.dump()
                            break
                if result:
                    print "Successfully ordered troop ship(s) to invade %s, with detail %s" % (planet_name, detail_str)
            # military
            elif AIFleetOrderType.ORDER_MILITARY == self.order_type:
                fleet_id = self.fleet.target_id
                #fo.issueFleetMoveOrder(fleet_id, self.target.target_id) #moving is already taken care of separately
                target_sys_id = self.target.target_id
                fleet = fo.getUniverse().getFleet(fleet_id)
                system_status = foAI.foAIstate.systemStatus.get(target_sys_id, {})
                if fleet and fleet.systemID == target_sys_id and not (system_status.get('fleetThreat', 0) + system_status.get('planetThreat', 0) + system_status.get('monsterThreat', 0)):
                    self.execution_completed = True

            # move or resupply
            elif self.order_type in [AIFleetOrderType.ORDER_MOVE, AIFleetOrderType.ORDER_REPAIR, AIFleetOrderType.ORDER_RESUPPLY]:
                fleet_id = self.fleet.target_id
                system_id = self.target.target_id
                fleet = fo.getUniverse().getFleet(fleet_id)
                if system_id not in [fleet.systemID, fleet.nextSystemID]:
                    if self.order_type == AIFleetOrderType.ORDER_MOVE:
                        dest_id = system_id
                    else:
                        if self.order_type == AIFleetOrderType.ORDER_REPAIR:
                            fo.issueAggressionOrder(fleet_id, False)
                        start_id = [fleet.systemID, fleet.nextSystemID][fleet.systemID == -1]
                        dest_id = MoveUtilsAI.get_safe_path_leg_to_dest(fleet_id, start_id, system_id)
                        print "fleet %d with order type(%s) sent to safe leg dest %s and ultimate dest %s" % (fleet_id, AIFleetOrderTypeNames.name(self.order_type),
                                                                                                            PlanetUtilsAI.sys_name_ids([dest_id]),
                                                                                                            PlanetUtilsAI.sys_name_ids([system_id]))
                    fo.issueFleetMoveOrder(fleet_id, dest_id)
                if system_id == fleet.systemID:
                    if foAI.foAIstate.get_fleet_role(fleet_id) == AIFleetMissionType.FLEET_MISSION_EXPLORATION:
                        if system_id in foAI.foAIstate.needsEmergencyExploration:
                            del foAI.foAIstate.needsEmergencyExploration[foAI.foAIstate.needsEmergencyExploration.index(system_id)]
                    self.execution_completed = True

            # split fleet
            elif AIFleetOrderType.ORDER_SPLIT_FLEET == self.order_type:
                fleet_id = self.fleet.target_id
                ship_id = self.target.target_id
                fleet = fo.getUniverse().getFleet(fleet_id)
                if ship_id in fleet.shipIDs:
                    fo.issueNewFleetOrder(str(ship_id), ship_id)
                self.execution_completed = True
            # attack
            elif AIFleetOrderType.ORDER_ATTACK == self.order_type:
                fleet_id = self.fleet.target_id
                fo.issueFleetMoveOrder(fleet_id, self.target.get_required_system_ai_targets()[0].target_id)
Example #31
0
    def generate_fleet_orders(self):
        """generates AIFleetOrders from fleets targets to accomplish"""
        universe = fo.getUniverse()
        fleet_id = self.target_id
        fleet = universe.getFleet(fleet_id)
        if (not fleet) or fleet.empty or (fleet_id in universe.destroyedObjectIDs(fo.empireID())):  # fleet was probably merged into another or was destroyed
            foAI.foAIstate.delete_fleet_info(fleet_id)
            return

        # TODO: priority
        self.clear_fleet_orders()
        system_id = fleet.systemID
        start_sys_id = [fleet.nextSystemID, system_id][system_id >= 0]
        # if fleet doesn't have any mission, then repair if needed or resupply if is current location not in supplyable system
        empire = fo.getEmpire()
        fleet_supplyable_system_ids = empire.fleetSupplyableSystemIDs
        #if (not self.hasAnyAIMissionTypes()):
        ntargets = 0
        for mission_type in self.get_mission_types():
            ntargets += len(self.get_targets(mission_type))
        if not ntargets and (system_id not in set(AIstate.colonyTargetedSystemIDs + AIstate.outpostTargetedSystemIDs +
                                                    AIstate.invasionTargetedSystemIDs + AIstate.blockadeTargetedSystemIDs)):
            if self._need_repair():
                repair_fleet_order = MoveUtilsAI.get_repair_fleet_order(self.target, start_sys_id)
                if repair_fleet_order.is_valid():
                    self.orders.append(repair_fleet_order)
            if self.get_location_target().target_id not in fleet_supplyable_system_ids:
                resupply_fleet_order = MoveUtilsAI.get_resupply_fleet_order(self.target, self.get_location_target())
                if resupply_fleet_order.is_valid():
                    self.orders.append(resupply_fleet_order)
            return  # no targets

        # for some targets fleet has to visit systems and therefore fleet visit them
        system_targets_required_to_visit = []
        for mission_type in self.get_mission_types():
            for aiTarget in self.get_targets(mission_type):
                system_targets_required_to_visit.extend(aiTarget.get_required_system_ai_targets())

        orders_to_visit_systems = MoveUtilsAI.get_fleet_orders_from_system_targets(self.target, system_targets_required_to_visit)
        #TODO: if fleet doesn't have enough fuel to get to final target, consider resetting Mission
        #print "----------------------------------------"
        #print "*+*+ fleet %d : has fleet action system targets: %s"%(fleet_id, [str(obj) for obj in system_targets_required_to_visit])
        #print "----------"
        #print "*+*+ fleet %d: has movement orders: %s"%(fleet_id, [str(obj) for obj in orders_to_visit_systems])

        for fleet_order in orders_to_visit_systems:
            self.orders.append(fleet_order)

        # if fleet is in some system = fleet.system_id >=0, then also generate system AIFleetOrders
        if system_id >= 0:
            # system in where fleet is
            system_target = AITarget(EnumsAI.AITargetType.TARGET_SYSTEM, system_id)
            # if mission aiTarget has required system where fleet is, then generate fleet_order from this aiTarget
            # for all targets in all mission types get required systems to visit
            for mission_type in self.get_mission_types():
                tragets = self.get_targets(mission_type)
                for target in tragets:
                    if system_target in target.get_required_system_ai_targets():
                        # from target required to visit get fleet orders to accomplish target
                        fleet_order = self._get_fleet_order_from_target(mission_type, target)
                        self.orders.append(fleet_order)
Example #32
0
def assign_scouts_to_explore_systems():
    # TODO: use Graph Theory to explore closest systems
    universe = fo.getUniverse()
    capital_sys_id = PlanetUtilsAI.get_capital_sys_id()
    # order fleets to explore
    if not border_unexplored_system_ids or (capital_sys_id == INVALID_ID):
        return
    exp_systems_by_dist = sorted((universe.linearDistance(capital_sys_id, x), x) for x in border_unexplored_system_ids)
    print "Exploration system considering following system-distance pairs:\n  %s" % ("\n  ".join("%3d: %5.1f" % info for info in exp_systems_by_dist))
    explore_list = [sys_id for dist, sys_id in exp_systems_by_dist]

    already_covered, available_scouts = get_current_exploration_info()

    print "Explorable system IDs: %s" % explore_list
    print "Already targeted: %s" % already_covered
    needs_vis = foAI.foAIstate.misc.setdefault('needs_vis', [])
    check_list = foAI.foAIstate.needsEmergencyExploration + needs_vis + explore_list
    if INVALID_ID in check_list:  # shouldn't normally happen, unless due to bug elsewhere
        for sys_list, name in [(foAI.foAIstate.needsEmergencyExploration, "foAI.foAIstate.needsEmergencyExploration"), (needs_vis, "needs_vis"), (explore_list, "explore_list")]:
            if INVALID_ID in sys_list:
                print_error("INVALID_ID found in " + name)
    needs_coverage = [sys_id for sys_id in check_list if sys_id not in already_covered and sys_id != INVALID_ID]  # emergency coverage can be due to invasion detection trouble, etc.
    print "Needs coverage: %s" % needs_coverage

    print "Available scouts & AIstate locs: %s" % [(x, foAI.foAIstate.fleetStatus.get(x, {}).get('sysID', INVALID_ID)) for x in available_scouts]
    print "Available scouts & universe locs: %s" % [(x, universe.getFleet(x).systemID) for x in available_scouts]
    if not needs_coverage or not available_scouts:
        return

    available_scouts = set(available_scouts)
    sent_list = []
    while available_scouts and needs_coverage:
        this_sys_id = needs_coverage.pop(0)
        sys_status = foAI.foAIstate.systemStatus.setdefault(this_sys_id, {})
        if this_sys_id not in explore_list:  # doesn't necessarily need direct visit
            if universe.getVisibility(this_sys_id, fo.empireID()) >= fo.visibility.partial:
                # already got visibility; remove from visit lists and skip
                if this_sys_id in needs_vis:
                    del needs_vis[needs_vis.index(this_sys_id)]
                if this_sys_id in foAI.foAIstate.needsEmergencyExploration:
                    del foAI.foAIstate.needsEmergencyExploration[
                        foAI.foAIstate.needsEmergencyExploration.index(this_sys_id)]
                print "system id %d already currently visible; skipping exploration" % this_sys_id
                continue
        # TODO: if blocked byu monster, try to find nearby system from which to see this system
        if not foAI.foAIstate.character.may_explore_system(sys_status.setdefault('monsterThreat', 0)) or (fo.currentTurn() < 20 and foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'] > 200):
            print "Skipping exploration of system %d due to Big Monster, threat %d" % (this_sys_id, foAI.foAIstate.systemStatus[this_sys_id]['monsterThreat'])
            continue
        this_fleet_list = FleetUtilsAI.get_fleets_for_mission(target_stats={}, min_stats={}, cur_stats={},
                                                              starting_system=this_sys_id, fleet_pool_set=available_scouts,
                                                              fleet_list=[])
        if not this_fleet_list:
            print "Seem to have run out of scouts while trying to cover sys_id %d" % this_sys_id
            break  # must have ran out of scouts
        fleet_id = this_fleet_list[0]
        fleet_mission = foAI.foAIstate.get_fleet_mission(fleet_id)
        target = universe_object.System(this_sys_id)
        if len(MoveUtilsAI.can_travel_to_system_and_return_to_resupply(fleet_id, fleet_mission.get_location_target(), target)) > 0:
            fleet_mission.set_target(MissionType.EXPLORATION, target)
            sent_list.append(this_sys_id)
        else:  # system too far out, skip it, but can add scout back to available pool
            print "sys_id %d too far out for fleet ( ID %d ) to reach" % (this_sys_id, fleet_id)
            available_scouts.update(this_fleet_list)
    print "Sent scouting fleets to sysIDs : %s" % sent_list
    return
    # pylint: disable=pointless-string-statement
    """