Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
import hooks;
|
||||
import artifacts;
|
||||
import resources;
|
||||
|
||||
import ai.consider;
|
||||
|
||||
#section server
|
||||
from empire import Creeps;
|
||||
#section all
|
||||
|
||||
interface Artifacts {
|
||||
Empire@ get_empire();
|
||||
Considerer@ get_consider();
|
||||
}
|
||||
|
||||
class ArtifactAI : Hook, ConsiderHook {
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class Value : ArtifactAI {
|
||||
Document doc("Sets the value for the artifact to a basic amount.");
|
||||
Argument value(AT_Decimal, doc="Value to set for the artifact.");
|
||||
|
||||
#section server
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class ActivateOnBestFleet : ArtifactAI {
|
||||
Document doc("This artifact should be activated on our strongest fleet that it can be.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating on the best fleet.");
|
||||
Argument min_strength(AT_Decimal, "1000", doc="Minimum strength for a fleet to be considered for this.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ fleet) const override {
|
||||
double str = fleet.getFleetStrength() * 0.001;
|
||||
if(str < min_strength.decimal)
|
||||
return 0.0;
|
||||
if(!cons.artifact.canTarget(fleet))
|
||||
return 0.0;
|
||||
return str;
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
@ai.consider.artifact = c;
|
||||
Object@ best = ai.consider.Fleets(this);
|
||||
if(best !is null) {
|
||||
c.setTarget(best);
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class ActivateOnBestPlanet : ArtifactAI {
|
||||
Document doc("This artifact should be activated on our best planet that it can be.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating on the best planet.");
|
||||
Argument min_population(AT_Decimal, "10", doc="Minimum population for a planet to be considered for this.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ planet) const override {
|
||||
double pop = planet.population;
|
||||
if(pop < min_population.decimal)
|
||||
return 0.0;
|
||||
if(!cons.artifact.canTarget(planet))
|
||||
return 0.0;
|
||||
return pop;
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
@ai.consider.artifact = c;
|
||||
Object@ best = ai.consider.ImportantPlanets(this);
|
||||
if(best !is null) {
|
||||
c.setTarget(best);
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class AsCreatedResource : ArtifactAI {
|
||||
Document doc("This artifact is used to spawn a new resource type on a planet that needs it.");
|
||||
Argument resource(AT_PlanetResource, doc="Resource to match import requests to.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating this.");
|
||||
Argument replaces_existing(AT_Boolean, "True", doc="Whether this can be used to replace an existing import of that type or not.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ requestedAt) const override {
|
||||
if(!cons.artifact.canTarget(requestedAt))
|
||||
return 0.0;
|
||||
if(cons.currentSupplier !is null)
|
||||
return 0.5;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
@ai.consider.artifact = c;
|
||||
Object@ best = ai.consider.MatchingImportRequests(this, getResource(resource.integer), replaces_existing.boolean);
|
||||
if(best !is null) {
|
||||
c.setTarget(best);
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class ActivateInOwnedSystem : ArtifactAI {
|
||||
Document doc("Activate this artifact on a position in an arbitrary owned system.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating this.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const override {
|
||||
Region@ sys = cast<Region>(obj);
|
||||
if(sys.PlanetsMask & ~cons.empire.mask != 0)
|
||||
return randomd(0.4, 0.6);
|
||||
return randomd(0.9, 1.1);
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
Region@ best = cast<Region>(ai.consider.OwnedSystems(this));
|
||||
if(best !is null) {
|
||||
vec3d position = best.position;
|
||||
vec2d offset = random2d(best.radius * 0.4, best.radius * 0.85);
|
||||
position.x += offset.x;
|
||||
position.z += offset.y;
|
||||
|
||||
if(!c.canTargetPosition(position))
|
||||
return false;
|
||||
|
||||
c.setTargetPosition(position);
|
||||
if(best.PlanetsMask & ~ai.empire.mask != 0)
|
||||
value *= 0.5;
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class ActivateNearOwnedSystem : ArtifactAI {
|
||||
Document doc("Activate this artifact on a position placed outside an arbitrary owned system.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating this.");
|
||||
Argument min_distance(AT_Decimal, "2000", doc="Minimum distance from the system boundary to place it.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const override {
|
||||
Region@ sys = cast<Region>(obj);
|
||||
if(sys.PlanetsMask & ~cons.empire.mask != 0)
|
||||
return randomd(0.4, 0.6);
|
||||
return randomd(0.9, 1.1);
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
Region@ best = cast<Region>(ai.consider.OwnedSystems(this));
|
||||
if(best !is null) {
|
||||
vec3d position = best.position;
|
||||
vec2d offset = random2d(best.radius + min_distance.decimal, best.radius + min_distance.decimal * 2.0);
|
||||
position.x += offset.x;
|
||||
position.z += offset.y;
|
||||
position.y += min_distance.decimal * randomd(0.0, 0.25);
|
||||
|
||||
if(!c.canTargetPosition(position))
|
||||
return false;
|
||||
|
||||
c.setTargetPosition(position);
|
||||
if(best.PlanetsMask & ~ai.empire.mask != 0)
|
||||
value *= 0.5;
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class AsVisionGain : ArtifactAI {
|
||||
Document doc("Activate this to gain vision over systems with other people in them we want to see.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating this.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const override {
|
||||
Region@ sys = cast<Region>(obj);
|
||||
if(sys.VisionMask & cons.empire.visionMask != 0)
|
||||
return 0.0;
|
||||
if(!cons.artifact.canTarget(sys))
|
||||
return 0.0;
|
||||
double w = 1.0;
|
||||
if(sys.PlanetsMask & cons.empire.hostileMask != 0)
|
||||
w *= 2.0;
|
||||
return w * randomd(0.9, 1.1);
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
@ai.consider.artifact = c;
|
||||
Region@ best = cast<Region>(ai.consider.OtherSystems(this));
|
||||
if(best !is null) {
|
||||
c.setTarget(best);
|
||||
value *= this.value.decimal;
|
||||
if(best.PlanetsMask & ai.empire.hostileMask != 0)
|
||||
value *= 2.0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class RevenantPart : ArtifactAI {
|
||||
Document doc("Special AI to deal with using parts of the revenant.");
|
||||
|
||||
#section server
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
//If we are subjugated don't use these
|
||||
if(ai.empire.SubjugatedBy !is null)
|
||||
return false;
|
||||
|
||||
value *= 10.0;
|
||||
//If we have parts ourselves, weight more
|
||||
value *= pow(2.0, ai.empire.RevenantParts);
|
||||
|
||||
//If an enemy has multilple parts, weight more
|
||||
for(uint i = 0, cnt = getEmpireCount(); i < cnt; ++i) {
|
||||
Empire@ other = getEmpire(i);
|
||||
if(!other.major || other !is ai.empire)
|
||||
value *= pow(3.0, other.RevenantParts);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class ActivateAsPressureBoost : ArtifactAI {
|
||||
Document doc("Activate this artifact on a planet to boost its pressure.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating on the best planet.");
|
||||
Argument pressure_amount(AT_Decimal, "1.0", doc="Amount of pressure that is added.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ planet) const override {
|
||||
auto@ res = getResource(planet.primaryResourceType);
|
||||
if(res is null)
|
||||
return 0.0;
|
||||
if(res.totalPressure < 1)
|
||||
return 0.0;
|
||||
double pres = planet.totalPressure;
|
||||
double cap = planet.pressureCap;
|
||||
if(pres + pressure_amount.decimal > cap * 1.5)
|
||||
return 0.0;
|
||||
if(!cons.artifact.canTarget(planet))
|
||||
return 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
@ai.consider.artifact = c;
|
||||
Object@ best = ai.consider.SomePlanets(this);
|
||||
Object@ existing = c.getTarget();
|
||||
if(existing !is null && consider(ai.consider, existing) > ai.consider.selectedWeight)
|
||||
@best = existing;
|
||||
if(best !is null) {
|
||||
c.setTarget(best);
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class ActivateOnRemnantStation : ArtifactAI {
|
||||
Document doc("Find remnant stations to trigger this on.");
|
||||
Argument value(AT_Decimal, "1.0", doc="Value for activating on the best station.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const override {
|
||||
Region@ reg = cast<Region>(obj);
|
||||
if(reg.getStrength(Creeps) > 0)
|
||||
return 1.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
bool consider(Artifacts& ai, ArtifactConsider& c, double& value) const override {
|
||||
@ai.consider.artifact = c;
|
||||
Object@ best;
|
||||
|
||||
Object@ reg = cast<Region>(ai.consider.OwnedSystems(this));
|
||||
if(reg !is null) {
|
||||
Object@ en = reg.findEnemy(ai.empire, Creeps.mask, fleets=false, stations=true);
|
||||
if(en !is null) {
|
||||
if(c.canTarget(en))
|
||||
@best = en;
|
||||
}
|
||||
}
|
||||
Object@ existing = c.getTarget();
|
||||
if(best is null && existing !is null && existing.valid && c.canTarget(existing))
|
||||
@best = existing;
|
||||
|
||||
if(best !is null) {
|
||||
c.setTarget(best);
|
||||
value *= this.value.decimal;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#section all
|
||||
};
|
||||
@@ -0,0 +1,141 @@
|
||||
import hooks;
|
||||
import buildings;
|
||||
import resources;
|
||||
|
||||
import ai.consider;
|
||||
|
||||
interface Buildings : ConsiderComponent {
|
||||
Empire@ get_empire();
|
||||
Considerer@ get_consider();
|
||||
|
||||
bool requestsFTLStorage();
|
||||
|
||||
bool isBuilding(const BuildingType& type);
|
||||
bool isFocus(Object@ obj);
|
||||
|
||||
void registerUse(BuildingUse use, const BuildingType& type);
|
||||
};
|
||||
|
||||
enum BuildingUse {
|
||||
BU_Factory,
|
||||
BU_LaborStorage,
|
||||
};
|
||||
|
||||
const array<string> BuildingUseName = {
|
||||
"Factory",
|
||||
"LaborStorage",
|
||||
};
|
||||
|
||||
class BuildingAI : Hook, ConsiderHook {
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void register(Buildings& buildings, const BuildingType& type) const {
|
||||
}
|
||||
|
||||
//Return the planet to build this building on
|
||||
Object@ considerBuild(Buildings& buildings, const BuildingType& type) const {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
class RegisterForUse : BuildingAI {
|
||||
Document doc("Register this building for a particular use. Only one building can be used for a specific specialized use.");
|
||||
Argument use(AT_Custom, doc="Specialized usage for this building.");
|
||||
|
||||
void register(Buildings& buildings, const BuildingType& type) const override {
|
||||
for(uint i = 0, cnt = BuildingUseName.length; i < cnt; ++i) {
|
||||
if(BuildingUseName[i] == use.str) {
|
||||
buildings.registerUse(BuildingUse(i), type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class AsCreatedResource : BuildingAI {
|
||||
Document doc("This building is used to spawn a new resource type on a planet that needs it.");
|
||||
Argument resource(AT_PlanetResource, doc="Resource to match import requests to.");
|
||||
Argument minimum_idle(AT_Decimal, "180", doc="Minimum amount of time the resource request has to have been idle to consider this.");
|
||||
Argument minimum_colonize_idle(AT_Decimal, "180", doc="Minimum amount of time since we've colonized something matching the request before we consider building this.");
|
||||
Argument minimum_gametime(AT_Decimal, "1500", doc="Minimum gametime that needs to have passed before we consider building this.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ requestedAt) const override {
|
||||
double w = 1.0;
|
||||
if(cons.currentSupplier !is null)
|
||||
return 0.0;
|
||||
if(cons.idleTime < minimum_idle.decimal)
|
||||
return 0.0;
|
||||
if(cons.timeSinceMatchingColonize() < minimum_colonize_idle.decimal)
|
||||
return 0.0;
|
||||
if(!cons.building.canBuildOn(requestedAt, ignoreState=true))
|
||||
return 0.0;
|
||||
return w;
|
||||
}
|
||||
|
||||
Object@ considerBuild(Buildings& buildings, const BuildingType& type) const override {
|
||||
if(gameTime < minimum_gametime.decimal)
|
||||
return null;
|
||||
@buildings.consider.building = type;
|
||||
return buildings.consider.MatchingImportRequests(this, getResource(resource.integer), false);
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class BuildForPressureCap : BuildingAI {
|
||||
Document doc("Build this to increase the pressure capacity on a planet.");
|
||||
Argument increase(AT_Integer, doc="Pressure this should increase the cap by.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const override {
|
||||
double w = 1.0;
|
||||
int pres = obj.totalPressure;
|
||||
int cap = obj.pressureCap;
|
||||
if(pres <= cap)
|
||||
return 0.0;
|
||||
if(obj.level <= 0)
|
||||
return 0.0;
|
||||
if(double(obj.population) < double(obj.maxPopulation) * 0.9)
|
||||
return 0.0;
|
||||
double eff = double(pres) / double(cap);
|
||||
if(eff < 1.5 && cap + increase.integer > 2 * pres)
|
||||
return 0.0;
|
||||
if(!cons.building.canBuildOn(obj, ignoreState=true))
|
||||
return 0.0;
|
||||
return eff;
|
||||
}
|
||||
|
||||
Object@ considerBuild(Buildings& buildings, const BuildingType& type) const override {
|
||||
@buildings.consider.building = type;
|
||||
return buildings.consider.SomePlanets(this);
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class AsFTLStorage : BuildingAI {
|
||||
Document doc("This building is built whenever more ftl storage is requested.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const override {
|
||||
if(cast<Buildings>(cons.component).isFocus(obj))
|
||||
return 0.0;
|
||||
if(obj.emptyDevelopedTiles < 10)
|
||||
return 0.0;
|
||||
if(!cons.building.canBuildOn(obj, ignoreState=true))
|
||||
return 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
Object@ considerBuild(Buildings& buildings, const BuildingType& type) const override {
|
||||
if(!buildings.requestsFTLStorage())
|
||||
return null;
|
||||
if(buildings.isBuilding(type))
|
||||
return null;
|
||||
@buildings.consider.component = buildings;
|
||||
@buildings.consider.building = type;
|
||||
return buildings.consider.SomePlanets(this);
|
||||
}
|
||||
#section all
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import resources;
|
||||
import buildings;
|
||||
|
||||
export Considerer;
|
||||
export ConsiderHook;
|
||||
export ArtifactConsider;
|
||||
|
||||
export ConsiderComponent;
|
||||
export ConsiderFilter;
|
||||
|
||||
interface ArtifactConsider {
|
||||
void setTarget(Object@ obj);
|
||||
Object@ getTarget();
|
||||
bool canTarget(Object@ obj);
|
||||
void setTargetPosition(const vec3d& pos);
|
||||
vec3d getTargetPosition();
|
||||
bool canTargetPosition(const vec3d& pos);
|
||||
};
|
||||
|
||||
interface ConsiderComponent {
|
||||
};
|
||||
|
||||
interface ConsiderFilter {
|
||||
bool filter(Object@ obj);
|
||||
};
|
||||
|
||||
interface Considerer {
|
||||
Empire@ get_empire();
|
||||
|
||||
Object@ get_currentSupplier();
|
||||
ArtifactConsider@ get_artifact();
|
||||
void set_artifact(ArtifactConsider@ cons);
|
||||
double get_selectedWeight();
|
||||
double get_idleTime();
|
||||
|
||||
const BuildingType@ get_building();
|
||||
void set_building(const BuildingType@ type);
|
||||
|
||||
ConsiderComponent@ get_component();
|
||||
void set_component(ConsiderComponent@ comp);
|
||||
void set_filter(ConsiderFilter@ filter);
|
||||
|
||||
//Consider all systems we currently have planets in
|
||||
Object@ OwnedSystems(const ConsiderHook& hook, uint limit = uint(-1));
|
||||
|
||||
//Consider all systems on our empire borders
|
||||
Object@ BorderSystems(const ConsiderHook& hook);
|
||||
|
||||
//Consider all systems we know other empires have planets in
|
||||
Object@ OtherSystems(const ConsiderHook& hook);
|
||||
|
||||
//Consider all our fleets
|
||||
Object@ Fleets(const ConsiderHook& hook);
|
||||
|
||||
//Consider planets we own that are important in some way
|
||||
Object@ ImportantPlanets(const ConsiderHook& hook);
|
||||
|
||||
//Consider all our planets
|
||||
Object@ AllPlanets(const ConsiderHook& hook);
|
||||
|
||||
//Consider a random selection of our planets
|
||||
Object@ SomePlanets(const ConsiderHook& hook, uint count = 5, bool alwaysImportant = true);
|
||||
|
||||
//Consider any planets we're using as factories to build things
|
||||
Object@ FactoryPlanets(const ConsiderHook& hook);
|
||||
|
||||
//Consider import requests that could be satisfied by the specified resource type
|
||||
Object@ MatchingImportRequests(const ConsiderHook& hook, const ResourceType@ type, bool considerExisting);
|
||||
//Time since the last colonization of theh import request we're currently considering
|
||||
double timeSinceMatchingColonize();
|
||||
};
|
||||
|
||||
interface ConsiderHook {
|
||||
double consider(Considerer& cons, Object@ object) const;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
import hooks;
|
||||
import orbitals;
|
||||
|
||||
import ai.consider;
|
||||
|
||||
interface AIOrbitals : ConsiderComponent {
|
||||
Empire@ get_empire();
|
||||
Considerer@ get_consider();
|
||||
|
||||
void registerUse(OrbitalUse use, const OrbitalModule& type);
|
||||
};
|
||||
|
||||
enum OrbitalUse {
|
||||
OU_Shipyard,
|
||||
};
|
||||
|
||||
const array<string> OrbitalUseName = {
|
||||
"Shipyard",
|
||||
};
|
||||
|
||||
class OrbitalAIHook : Hook, ConsiderHook {
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void register(AIOrbitals& orbitals, const OrbitalModule& type) const {
|
||||
}
|
||||
|
||||
//Return a system or a planet to build this orbital in/around
|
||||
Object@ considerBuild(AIOrbitals& orbitals, const OrbitalModule& type) const {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
class RegisterForUse : OrbitalAIHook {
|
||||
Document doc("Register this orbital for a particular use. Only one orbital can be used for a specific specialized use.");
|
||||
Argument use(AT_Custom, doc="Specialized usage for this orbital.");
|
||||
|
||||
void register(AIOrbitals& orbitals, const OrbitalModule& type) const override {
|
||||
for(uint i = 0, cnt = OrbitalUseName.length; i < cnt; ++i) {
|
||||
if(OrbitalUseName[i] == use.str) {
|
||||
orbitals.registerUse(OrbitalUse(i), type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
import hooks;
|
||||
import resources;
|
||||
|
||||
import ai.consider;
|
||||
|
||||
interface AIResources : ConsiderComponent {
|
||||
Empire@ get_empire();
|
||||
Considerer@ get_consider();
|
||||
};
|
||||
|
||||
class ResourceAI : Hook, ConsiderHook {
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
//If the AI is not currently using this resource for anything
|
||||
//that explicitly requested it, this hook determines where it will
|
||||
//be distributed to in the meantime. Returning null means it will not be
|
||||
//placed anywhere.
|
||||
Object@ distribute(AIResources& ai, const ResourceType& type, Object@ current) const {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
class DistributeToImportantPlanet : ResourceAI {
|
||||
Document doc("This resource goes to important planets to make them better.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
return 1.0 + obj.level;
|
||||
}
|
||||
|
||||
Object@ distribute(AIResources& ai, const ResourceType& type, Object@ current) const {
|
||||
if(current !is null)
|
||||
return current;
|
||||
return ai.consider.ImportantPlanets(this);
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class DistributeToLaborUsing : ResourceAI {
|
||||
Document doc("This resource gets distributed to planets building things with labor.");
|
||||
Argument remove_idle(AT_Boolean, "True", doc="Remove the resource again when the target goes idle.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
if(obj.constructionCount == 0)
|
||||
return 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
Object@ distribute(AIResources& ai, const ResourceType& type, Object@ current) const {
|
||||
if(current !is null) {
|
||||
if(!remove_idle.boolean || current.constructionCount != 0)
|
||||
return current;
|
||||
}
|
||||
return ai.consider.FactoryPlanets(this);
|
||||
}
|
||||
#section all
|
||||
};
|
||||
|
||||
class DistributeAsLocalPressureBoost : ResourceAI {
|
||||
Document doc("This resource gets distributed to boost the native pressure of a resource.");
|
||||
Argument amount(AT_Integer, doc="Amount of pressure this boosts by.");
|
||||
|
||||
#section server
|
||||
double consider(Considerer& cons, Object@ obj) const {
|
||||
auto@ resource = getResource(obj.primaryResourceType);
|
||||
if(resource is null)
|
||||
return 0.0;
|
||||
if(resource.totalPressure <= 0)
|
||||
return 0.0;
|
||||
bool havePressure = obj.owner.HasPressure != 0.0;
|
||||
if(havePressure) {
|
||||
int presCap = obj.pressureCap;
|
||||
int presUse = obj.totalPressure;
|
||||
if(presUse + amount.integer <= presCap)
|
||||
return 1.0;
|
||||
return 0.0;
|
||||
}
|
||||
else {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
Object@ distribute(AIResources& ai, const ResourceType& type, Object@ current) const {
|
||||
if(current !is null) {
|
||||
int presCap = current.pressureCap;
|
||||
int presUse = current.totalPressure;
|
||||
if(presUse <= presCap)
|
||||
return current;
|
||||
}
|
||||
Object@ check = ai.consider.SomePlanets(this);
|
||||
if(check !is null)
|
||||
return check;
|
||||
else
|
||||
return current;
|
||||
}
|
||||
#section all
|
||||
};
|
||||
Reference in New Issue
Block a user