import freeOrionAIInterface as fo
import FreeOrionAI as foAI
from EnumsAI import AITargetType, AIFleetOrderType
import AITarget
import AIFleetOrder
from ColonisationAI import annexableSystemIDs, annexableRing1, annexableRing2, annexableRing3
import PlanetUtilsAI
def getAIFleetOrdersFromSystemAITargets(fleetAITarget, aiTargets):
result = []
# TODO: use Graph Theory to construct move orders
# TODO: add priority
empireID = fo.empireID()
# determine system where fleet will be or where is if is going nowhere
lastSystemAITarget = fleetAITarget.getRequiredSystemAITargets()[0]
# for every system which fleet wanted to visit, determine systems to visit and create move orders
for aiTarget in aiTargets:
# determine systems required to visit(with possible return to supplied system)
#print "checking system targets"
systemAITargets = canTravelToSystem(fleetAITarget.getTargetID(), lastSystemAITarget, aiTarget, empireID)
#print "making path with %d targets: "%len(systemAITargets) , PlanetUtilsAI.sysNameIDs( [sysTarg. getTargetID() for sysTarg in systemAITargets])
if len(systemAITargets) > 0:
# for every system required to visit create move order
for systemAITarget in systemAITargets:
# remember last system which will be visited
lastSystemAITarget = systemAITarget
# create move order
aiFleetOrder = AIFleetOrder.AIFleetOrder(AIFleetOrderType.ORDER_MOVE, fleetAITarget, systemAITarget)
result.append(aiFleetOrder)
else:
startSysID = lastSystemAITarget.getTargetID()
targetSysID = aiTarget.getTargetID()
if startSysID != targetSysID:
print "fleetID: " + str(fleetAITarget.getTargetID()) + " can't travel to target:" + str(aiTarget)
return result
def canTravelToSystem(fleetID, fromSystemAITarget, toSystemAITarget, empireID, ensureReturn=False):
empire = fo.getEmpire()
fleetSupplyableSystemIDs = set(empire.fleetSupplyableSystemIDs)
# get current fuel and max fuel
universe = fo.getUniverse()
fleet = universe.getFleet(fleetID)
maxFuel = int(fleet.maxFuel)
fuel = int(fleet.fuel)
if fuel < 1.0 or fromSystemAITarget.getTargetID() == toSystemAITarget.getTargetID:
return []
if foAI.foAIstate.aggression<=fo.aggression.typical or True: #TODO: sort out if shortestPath leaves off some intermediate destinations
pathFunc=universe.leastJumpsPath
else:
pathFunc=universe.shortestPath
startSysID = fromSystemAITarget.getTargetID()
targetSysID = toSystemAITarget.getTargetID()
shortPath= list( pathFunc(startSysID, targetSysID, empireID) )
suppliedStops = [ sid for sid in shortPath if sid in fleetSupplyableSystemIDs ]
unsuppliedStops = [sid for sid in shortPath if sid not in suppliedStops ]
retPath=[]
#print "getting path from %s to %s "%(PlanetUtilsAI.sysNameIDs([ startSysID ]), PlanetUtilsAI.sysNameIDs([ targetSysID ]) ),
#print " ::: found initial path %s having suppliedStops %s and unsuppliedStops %s ; tot fuel available is %.1f"%( PlanetUtilsAI.sysNameIDs( shortPath[:] ), suppliedStops, unsuppliedStops, fuel)
if False:
if targetSysID in fleetSupplyableSystemIDs:
print "target has FleetSupply"
elif targetSysID in annexableRing1:
print "target in Ring 1"
elif targetSysID in annexableRing2:
print "target in Ring 2, has enough aggression is ", foAI.foAIstate.aggression >=fo.aggression.typical
elif targetSysID in annexableRing3:
print "target in Ring 2, has enough aggression is ", foAI.foAIstate.aggression >=fo.aggression.aggressive
if ( len( unsuppliedStops) == 0 or
targetSysID in fleetSupplyableSystemIDs and len( unsuppliedStops) < fuel or
targetSysID in annexableRing1 and len( unsuppliedStops) < fuel or
foAI.foAIstate.aggression >=fo.aggression.typical and targetSysID in annexableRing2 and len( unsuppliedStops) < fuel -1 or
foAI.foAIstate.aggression >=fo.aggression.aggressive and targetSysID in annexableRing3 and len( unsuppliedStops) < fuel -2 ):
retPath = [ AITarget.AITarget(AITargetType.TARGET_SYSTEM, sid) for sid in shortPath]
else:
#print " getting path from 'canTravelToSystemAndReturnToResupply' ",
retPath = canTravelToSystemAndReturnToResupply(fleetID, fromSystemAITarget, toSystemAITarget, empireID, verbose=True)
return retPath
def canTravelToSystemAndReturnToResupply(fleetID, fromSystemAITarget, toSystemAITarget, empireID, verbose=False):
"check if fleet can travel from starting system to wanted system"
systemAITargets = []
if not fromSystemAITarget.getTargetID() == toSystemAITarget.getTargetID:
# get supplyable systems
empire = fo.getEmpire()
fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
# get current fuel and max fuel
universe = fo.getUniverse()
fleet = universe.getFleet(fleetID)
maxFuel = int(fleet.maxFuel)
fuel = int(fleet.fuel)
if verbose:
print " fleet ID %d has %.1f fuel to get from %s to %s"%(fleetID, fuel, fromSystemAITarget, toSystemAITarget )
# try to find path without going resupply first
supplySystemAITarget = getNearestSuppliedSystem(toSystemAITarget.getTargetID(), empireID)
__findPathWithFuelToSystemWithPossibleReturn(fromSystemAITarget, toSystemAITarget, empireID, systemAITargets, fleetSupplyableSystemIDs, maxFuel, fuel, supplySystemAITarget)
# resupply in system first is required to find path
if not(fromSystemAITarget.getTargetID() in fleetSupplyableSystemIDs) and len(systemAITargets) == 0:
# add supply system to visit
fromSystemAITarget = getNearestSuppliedSystem(fromSystemAITarget.getTargetID(), empireID)
systemAITargets.append(fromSystemAITarget)
# find path from supplied system to wanted system
__findPathWithFuelToSystemWithPossibleReturn(fromSystemAITarget, toSystemAITarget, empireID, systemAITargets, fleetSupplyableSystemIDs, maxFuel, maxFuel, supplySystemAITarget)
return systemAITargets
def getNearestSuppliedSystem(startSystemID, empireID):
"returns systemAITarget of nearest supplied system from starting system startSystemID"
empire = fo.getEmpire()
fleetSupplyableSystemIDs = empire.fleetSupplyableSystemIDs
universe = fo.getUniverse()
if startSystemID in fleetSupplyableSystemIDs:
return AITarget.AITarget(AITargetType.TARGET_SYSTEM, startSystemID)
else:
minJumps = 9999 # infinity
supplySystemID = -1
for systemID in fleetSupplyableSystemIDs:
leastJumpsPath = universe.leastJumpsPath(startSystemID, systemID, empireID)
if len(leastJumpsPath) < minJumps:
minJumps = len(leastJumpsPath)
supplySystemID = systemID
return AITarget.AITarget(AITargetType.TARGET_SYSTEM, supplySystemID)
def __findPathWithFuelToSystemWithPossibleReturn(fromSystemAITarget, toSystemAITarget, empireID, resultSystemAITargets, fleetSupplyableSystemIDs, maxFuel, fuel, supplySystemAITarget):
"returns system AITargets required to visit with fuel to nearest supplied system"
result = True
# try to find if there is possible path to wanted system from system
newTargets = resultSystemAITargets[:]
if fromSystemAITarget.isValid() and toSystemAITarget.isValid() and supplySystemAITarget.isValid():
universe = fo.getUniverse()
leastJumpsPath = universe.leastJumpsPath(fromSystemAITarget.getTargetID(), toSystemAITarget.getTargetID(), empireID)
fromSystemID = fromSystemAITarget.getTargetID()
for systemID in leastJumpsPath:
if not fromSystemID == systemID:
if fromSystemID in fleetSupplyableSystemIDs:
# from supplied system fleet can travel without fuel consumption and also in this system refuels
fuel = maxFuel
else:
fuel = fuel - 1
# leastJumpPath can differ from shortestPath
# TODO: use Graph Theory to optimize
if True or ((not systemID == toSystemAITarget.getTargetID()) and (systemID in fleetSupplyableSystemIDs)):#TODO: restructure
newTargets.append(AITarget.AITarget(AITargetType.TARGET_SYSTEM, systemID))
if fuel < 0:
result = False
fromSystemID = systemID
else:
result = False
# if there is path to wanted system, then also if there is path back to supplyable system
if result == True:
# jump from A to B means leastJumpsPath=[A,B], but minJumps=1
minJumps = len(universe.leastJumpsPath(toSystemAITarget.getTargetID(), supplySystemAITarget.getTargetID(), empireID)) - 1
if minJumps > fuel:
# print "fleetID:" + str(fleetID) + " fuel:" + str(fuel) + " required: " + str(minJumps)
result = False
#else:
#resultSystemAITargets.append(toSystemAITarget)
if result == False:
return []
resultSystemAITargets[:] = newTargets
return resultSystemAITargets
def getResupplyAIFleetOrder(fleetAITarget, currentSystemAITarget):
"returns resupply AIFleetOrder to nearest supplied system"
# find nearest supplied system
empireID = fo.empireID()
suppliedSystemAITarget = getNearestSuppliedSystem(currentSystemAITarget.getTargetID(), empireID)
# create resupply AIFleetOrder
aiFleetOrder = AIFleetOrder.AIFleetOrder(AIFleetOrderType.ORDER_RESUPPLY, fleetAITarget, suppliedSystemAITarget)
return aiFleetOrder