diff --git a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js index 5efac24b4b..f95b8b3a53 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -626,12 +626,11 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses) var current = this.getEntityCounts(); for (let trainable of allTrainable) { - let template = this.getTemplate(trainable); - - if (!template || !template.available(this)) - continue; if (this.isDisabledTemplates(trainable)) continue; + let template = this.getTemplate(trainable); + if (!template || !template.available(this)) + continue; let okay = true; for (let clas of classes) diff --git a/binaries/data/mods/public/simulation/ai/petra/baseManager.js b/binaries/data/mods/public/simulation/ai/petra/baseManager.js index 510d403ea1..a881361558 100644 --- a/binaries/data/mods/public/simulation/ai/petra/baseManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/baseManager.js @@ -462,6 +462,18 @@ m.BaseManager.prototype.checkResourceLevels = function (gameState, queues) queues.field.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base": this.ID })); } } + else if (gameState.isDisabledTemplates(gameState.applyCiv("structures/{civ}_field")) && + !queues.corral.hasQueuedUnits() && + gameState.getOwnEntitiesByClass("Corral", true).length === 0 && + gameState.ai.HQ.canBuild(gameState, "structures/{civ}_corral")) + { + let count = this.getResourceLevel(gameState, type, (gameState.currentPhase() > 1)); // animals are not accounted + if (count < 600) + { + queues.corral.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_corral", { "base": this.ID })); + gameState.ai.HQ.needCorral = true; + } + } } else if (!queues.dropsites.hasQueuedUnits() && !gameState.getOwnFoundations().filter(API3.Filters.byClass("Storehouse")).length) { diff --git a/binaries/data/mods/public/simulation/ai/petra/config.js b/binaries/data/mods/public/simulation/ai/petra/config.js index 2ef9a869ba..e9ae59f441 100644 --- a/binaries/data/mods/public/simulation/ai/petra/config.js +++ b/binaries/data/mods/public/simulation/ai/petra/config.js @@ -79,21 +79,22 @@ m.Config = function(difficulty) this.priorities = { - "villager" : 30, // should be slightly lower than the citizen soldier one to not get all the food - "citizenSoldier" : 60, - "trader" : 50, - "ships" : 70, - "house" : 350, - "dropsites" : 200, - "field" : 400, - "dock" : 90, - "economicBuilding" : 90, - "militaryBuilding" : 130, - "defenseBuilding" : 70, - "civilCentre" : 950, - "majorTech" : 700, - "minorTech" : 40, - "emergency" : 1000 // used only in emergency situations, should be the highest one + "villager": 30, // should be slightly lower than the citizen soldier one to not get all the food + "citizenSoldier": 60, + "trader": 50, + "ships": 70, + "house": 350, + "dropsites": 200, + "field": 400, + "dock": 90, + "corral": 60, + "economicBuilding": 90, + "militaryBuilding": 130, + "defenseBuilding": 70, + "civilCentre": 950, + "majorTech": 700, + "minorTech": 40, + "emergency": 1000 // used only in emergency situations, should be the highest one }; this.personality = diff --git a/binaries/data/mods/public/simulation/ai/petra/headquarters.js b/binaries/data/mods/public/simulation/ai/petra/headquarters.js index 672fe3f342..27e4d546c1 100644 --- a/binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ b/binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -105,16 +105,14 @@ m.HQ.prototype.getSeaIndex = function (gameState, index1, index2) var path = gameState.ai.accessibility.getTrajectToIndex(index1, index2); if (path && path.length == 3 && gameState.ai.accessibility.regionType[path[1]] === "water") return path[1]; - else + + if (this.Config.debug > 1) { - if (this.Config.debug > 1) - { - API3.warn("bad path from " + index1 + " to " + index2 + " ??? " + uneval(path)); - API3.warn(" regionLinks start " + uneval(gameState.ai.accessibility.regionLinks[index1])); - API3.warn(" regionLinks end " + uneval(gameState.ai.accessibility.regionLinks[index2])); - } - return undefined; + API3.warn("bad path from " + index1 + " to " + index2 + " ??? " + uneval(path)); + API3.warn(" regionLinks start " + uneval(gameState.ai.accessibility.regionLinks[index1])); + API3.warn(" regionLinks end " + uneval(gameState.ai.accessibility.regionLinks[index2])); } + return undefined; }; m.HQ.prototype.checkEvents = function (gameState, events, queues) @@ -321,6 +319,29 @@ m.HQ.prototype.checkEvents = function (gameState, events, queues) base.reassignIdleWorkers(gameState, [ent]); base.workerObject.update(gameState, ent); } + else if (ent.resourceSupplyType() && ent.position()) + { + let type = ent.resourceSupplyType(); + if (!type.generic) + continue; + let dropsites = gameState.getOwnDropsites(type.generic); + let pos = ent.position(); + let access = gameState.ai.accessibility.getAccessValue(pos); + let distmin = Math.min(); + let goal; + for (let dropsite of dropsites.values()) + { + if (!dropsite.position() || dropsite.getMetadata(PlayerID, "access") !== access) + continue; + let dist = API3.SquareVectorDistance(pos, dropsite.position()); + if (dist > distmin) + continue; + distmin = dist; + goal = dropsite.position(); + } + if (goal) + ent.moveToRange(goal[0], goal[1]); + } } } @@ -1278,6 +1299,47 @@ m.HQ.prototype.buildFarmstead = function(gameState, queues) queues.economicBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_farmstead")); }; +// Build a corral, and train animals there +m.HQ.prototype.manageCorral = function(gameState, queues) +{ + if (queues.corral.hasQueuedUnits()) + return; + + // Only build one corral for the time being + if (gameState.getOwnEntitiesByClass("Corral", true).length === 0) + { + if (!this.canBuild(gameState, "structures/{civ}_corral")) + return; + let template = gameState.applyCiv("structures/{civ}_corral"); + if (this.canBuild(gameState, template)) + queues.corral.addPlan(new m.ConstructionPlan(gameState, template)); + return; + } + + // And train some animals + for (let corral of gameState.getOwnEntitiesByClass("Corral", true).values()) + { + if (corral.foundationProgress() !== undefined) + continue; + let trainables = corral.trainableEntities(""); + for (let trainable of trainables) + { + if (gameState.isDisabledTemplates(trainable)) + continue; + let template = gameState.getTemplate(trainable); + if (!template || !template.isHuntable()) + continue; + let count = gameState.countEntitiesByType(trainable, true); + for (let item of corral.trainingQueue()) + count += item.count; + if (count > 1) + continue; + queues.corral.addPlan(new m.TrainingPlan(gameState, trainable, { "trainer": corral.id() })); + return; + } + } +}; + // build more houses if needed. // kinda ugly, lots of special cases to both build enough houses but not tooo many… m.HQ.prototype.buildMoreHouses = function(gameState,queues) @@ -2019,6 +2081,9 @@ m.HQ.prototype.update = function(gameState, queues, events) if (!this.saveResources && gameState.ai.playedTurn % 4 == 2) this.buildFarmstead(gameState, queues); + if (this.needCorral && gameState.ai.playedTurn % 4 == 3) + this.manageCorral(gameState, queues); + if (!queues.minorTech.hasQueuedUnits() && gameState.ai.playedTurn % 5 == 1) this.researchManager.update(gameState, queues); } diff --git a/binaries/data/mods/public/simulation/ai/petra/queueManager.js b/binaries/data/mods/public/simulation/ai/petra/queueManager.js index 98ca25907f..1464c8b75f 100644 --- a/binaries/data/mods/public/simulation/ai/petra/queueManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/queueManager.js @@ -431,6 +431,9 @@ m.QueueManager.prototype.checkPausedQueues = function(gameState) if (q === "field" && gameState.ai.HQ.needFarm && gameState.getOwnStructures().filter(API3.Filters.byClass("Field")).length === 0) toBePaused = false; + if (q === "corral" && gameState.ai.HQ.needCorral && + gameState.getOwnStructures().filter(API3.Filters.byClass("Field")).length === 0) + toBePaused = false; if (q === "dock" && gameState.ai.HQ.needFish && gameState.getOwnStructures().filter(API3.Filters.byClass("Dock")).length === 0) toBePaused = false; diff --git a/binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js b/binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js index c2aaaa2f7e..c8d18610d4 100644 --- a/binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js +++ b/binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js @@ -212,7 +212,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState) if (ent.resourceDropsiteTypes() && ent.resourceDropsiteTypes().indexOf("food") !== -1) { - if (template.hasClass("Field")) + if (template.hasClass("Field") || template.hasClass("Corral")) placement.addInfluence(x, z, 80/cellSize, 50); else // If this is not a field add a negative influence because we want to leave this area for fields placement.addInfluence(x, z, 80/cellSize, -20); @@ -227,7 +227,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState) else if (!ent.hasClass("StoneWall") || ent.hasClass("Gates")) placement.addInfluence(x, z, 60/cellSize, -40); // and further away from other stuffs } - else if (template.hasClass("Farmstead") && (!ent.hasClass("Field") && + else if (template.hasClass("Farmstead") && (!ent.hasClass("Field") && !ent.hasClass("Corral") && (!ent.hasClass("StoneWall") || ent.hasClass("Gates")))) placement.addInfluence(x, z, 100/cellSize, -25); // move farmsteads away to make room (StoneWall test needed for iber) else if (template.hasClass("GarrisonFortress") && ent.genericName() == "House") diff --git a/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js b/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js index 7911f6a80d..6e71d4dd86 100644 --- a/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js +++ b/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js @@ -491,6 +491,11 @@ m.HQ.prototype.configFirstBase = function(gameState) { this.saveResources = true; this.Config.Economy.popForTown = 40; // Switch to town phase as soon as possible to be able to expand + if (startingWood < 2000 && this.needFarm) + { + this.needCorral = true; + this.needFarm = false; + } } if (startingWood > 8500 && this.canBuildUnits) { @@ -517,6 +522,13 @@ m.HQ.prototype.configFirstBase = function(gameState) gameState.ai.queues.dropsites.addPlan(new m.ConstructionPlan(gameState, template, { "base": this.baseManagers[1].ID }, newDP.pos)); } } + // and build immediately a corral if not much wood + if (this.needCorral) + { + template = gameState.applyCiv("structures/{civ}_corral"); + if (gameState.getOwnEntitiesByClass("Corral", true).length === 0 && this.canBuild(gameState, template)) + gameState.ai.queues.corral.addPlan(new m.ConstructionPlan(gameState, template, { "base": this.baseManagers[1].ID })); + } }; return m;