User:The Silent One/colonisation code
From FreeOrionWiki
import freeOrionAIInterface as fo import pickle # known issue: several colonyships can be sent to the same planet # AI must keep track of planets to which it has sent colony ships just like with exploration (change RemoveUnsuitablePlanets accordingly) # moving fleets with colony ship are intercepted and send to colonize # currently only uses size and hospitality score # later: specials, exploration, distance # minimal value a planet must have to be colonised minimal_colonise_value = 5 class planet_value(object): def __init__(self, ID=0, value=0): self.ID = ID self.value = value def GenerateColonisationOrders(): fo.LogOutput("Generating Colonisation Orders") empire = fo.GetEmpire() empire_id = fo.EmpireID() universe = fo.GetUniverse() # Look for stationary colonyships colonyship_ids = GetColonyshipIDs(empire_id, universe) if len(colonyship_ids) == 0: return fo.LogOutput("Available colony ships: " + str(colonyship_ids)) # Colonize Target Planets (if colonyship has arrived) ColoniseTargetPlanets(colonyship_ids, universe) # Search for suitable planets system_ids = GetExploredSystemIDs(empire, universe) planet_ids = GetPlanetsInSystemsIDs(system_ids, universe) fo.LogOutput("All planets in range: " + str(planet_ids)) RemoveUnsuitablePlanetIDs(planet_ids, universe) fo.LogOutput("Uncolonized planets without colony ship en route: " + str(planet_ids)) # Judge Planet Colonisation Values, remove bad planets evaluated_planets = AssignColonisationValue(planet_ids, universe) RemoveBadPlanets(evaluated_planets) evaluated_planets.sort(key=value) # correct sorting? if len(evaluated_planets) == 0: return fo.LogOutput("Attractive planets: " + str(evaluated_planets[0:-1].ID) + " Value: " + str(evaluated_planets[0:-1].value)) # Send Colony Ships SendColonyShips(colonyship_ids, evaluated_planets) # Helper functions, NOT to be called externally since globals will not be initialized def GetColonyshipIDs(empireID, universe): fo.LogOutput("GetEmpireStationaryColonyFleetIDs") ship_ids = [] object_ids = universe.ObjectIDs() for obj_id in object_ids: ship = universe.GetShip(obj_id) if (ship == None): continue # it's not a ship if (not ship.whollyOwnedBy(empire_id)): continue # it's not owned by the AI if (not ship.design.name = 'Colony Ship'): continue # it's no colony ship ship_ids.append(obj_id) return ship_ids def ColoniseTargetPlanets(colonyship_ids, universe): # probably needs change in C++ code, see below fo.LogOutput("Colonise Planets") for colonyship_id in colonyship_ids: colonyship = universe.GetShip(colonyship_id) if (colonyship == None): continue if colonyship.systemID == colonyship.destinationID: # colonyship.destinationID? print "colonizing " + colonyship.destinationID fo.issueColonizeOrder(colonyship_id, colonyship.destinationID) def GetExploredSystemIDs(empire, universe): fo.LogOutput("GetExploredSystemIDs") system_ids = [] object_ids = universe.ObjectIDs() for obj_id in object_ids: system = universe.GetSystem(obj_id) if (system == None): continue fo.LogOutput("...is a system") if (empire.HasExploredSystem(obj_id)): system_ids.append(obj_id) fo.LogOutput("...is explored") return system_ids def GetPlanetsInSystemsIDs(system_ids, universe): # may need change in C++ code or is an appropriate function available? fo.LogOutput("GetPlanetsInSystemsIDs") planet_ids = [] for system_id in system_ids: system = universe.GetSystem(system_id) if (system == None): continue planet_ids.extend(system.orbits) # System.Orbits?? return planet_ids def RemoveUnsuitablePlanetIDs(planet_ids, universe): fo.LogOutput("RemovePlanetIDs (Occupied, ToBeColonized)") for planet_id in planet_ids: planet = universe.GetPlanet(planet_id) if (planet == None): continue if not (planet.unowned): planet_ids.remove(planet_id) #if not (planet.NoColonyShipEnRoute): planet_ids_list = planet_ids_list - [planet_id] return planet_ids def AssignColonisationValue(planet_ids, universe): fo.LogOutput("AssignColonisationValue") # assign colonisation values to ids planet_values = [] for planet_id in planet_ids: value = planet_value(planet_id, EvaluatePlanet(planet_id, universe)) planet_values.append(value) return planet_values def EvaluatePlanet(planet_id, universe): fo.LogOutput("Evaluating planets") return GetPlanetHospitality(planet_id, universe) * planet.size # planet.size? def GetPlanetHospitality(planet_id, universe): planet = universe.GetPlanet(planet_id) if planet = None: return 0 # should be reworked with races if planet.type == fo.planetType.gaia: return 3 if planet.type == fo.planetType.terran: return 2 if planet.type == fo.planetType.ocean: return 1 if planet.type == fo.planetType.desert: return 1 if planet.type == fo.planetType.tundra: return 0.5 if planet.type == fo.planetType.swamp: return 0.5 return 0 def RemoveBadPlanets(evaluated_planets) for p_value in evaluated_planets: if p_value.value < minimal_colonise_value: evaluated_planets.remove(p_value) def SendColonyShips(colonyship_ids, evaluated_planets, universe) for i in range(0, colonyship_ids.len): if i > len(evaluated_planets): return # quit if there are more ships than planets colonyship = universe.GetShip(colonyship_ids[i]) IssueFleetMoveOrder(colonyship.fleetID, evaluated_planets[i].ID) # colonyship.fleetID? # set colonyship.destination