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)
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)
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)
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)
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)
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)
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
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
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
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
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
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
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 """
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 """
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 """
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)
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
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
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
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
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 """
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 []
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)
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)
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)
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)
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 []
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)
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)
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 """