petra: allow elephant stables for all civs, and some internal cleanups

This was SVN commit r20399.
This commit is contained in:
mimo 2017-11-02 16:16:11 +00:00
parent bff1f33bfd
commit 2ead236afe
3 changed files with 60 additions and 55 deletions

View file

@ -56,7 +56,7 @@ m.Config = function(difficulty)
"gaul": [ "structures/{civ}_rotarymill", "structures/{civ}_tavern" ],
"iber": [ "structures/{civ}_monument" ],
"mace": [ "structures/{civ}_library", "structures/{civ}_theatron" ],
"maur": [ "structures/{civ}_elephant_stables", "structures/{civ}_pillar_ashoka" ],
"maur": [ "structures/{civ}_pillar_ashoka" ],
"pers": [ "structures/{civ}_apadana", "structures/{civ}_hall"],
"ptol": [ "structures/{civ}_library" ],
"rome": [ "structures/{civ}_army_camp" ],

View file

@ -1758,44 +1758,38 @@ m.HQ.prototype.constructTrainingBuildings = function(gameState, queues)
if (numBarracks == 0)
{
gameState.ai.queueManager.changePriority("militaryBuilding", 2*this.Config.priorities.militaryBuilding);
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
let plan = new m.ConstructionPlan(gameState, "structures/{civ}_barracks", metadata);
let plan = new m.ConstructionPlan(gameState, "structures/{civ}_barracks", { "militaryBase": true });
plan.queueToReset = "militaryBuilding";
queues.militaryBuilding.addPlan(plan);
return;
}
if (numStables == 0)
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_stables", metadata));
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_stables", { "militaryBase": true }));
return;
}
// Second barracks and stables
if (numBarracks == 1 && gameState.getPopulation() > this.Config.Military.popForBarracks2)
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_barracks", metadata));
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_barracks", { "militaryBase": true }));
return;
}
if (numStables == 1 && gameState.getPopulation() > this.Config.Military.popForBarracks2)
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_stables", metadata));
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_stables", { "militaryBase": true }));
return;
}
// Then 3rd barracks/stables if needed
if (numBarracks == 2 && numStables == -1 && gameState.getPopulation() > this.Config.Military.popForBarracks2 + 30)
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_barracks", metadata));
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_barracks", { "militaryBase": true }));
return;
}
if (numBarracks == -1 && numStables == 2 && gameState.getPopulation() > this.Config.Military.popForBarracks2 + 30)
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_stables", metadata));
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_stables", { "militaryBase": true }));
return;
}
}
@ -1806,11 +1800,15 @@ m.HQ.prototype.constructTrainingBuildings = function(gameState, queues)
if (this.currentPhase < 3)
return;
let numWorkshop = this.canBuild(gameState, "structures/{civ}_siege_workshop") ? gameState.getOwnEntitiesByClass("Workshop", true).length : -1;
if (numWorkshop == 0)
if (this.canBuild(gameState, "structures/{civ}_elephant_stables") && !gameState.getOwnEntitiesByClass("ElephantStables", true).hasEntities())
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_siege_workshop", metadata));
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_elephant_stables", { "militaryBase": true }));
return;
}
if (this.canBuild(gameState, "structures/{civ}_siege_workshop") && !gameState.getOwnEntitiesByClass("Workshop", true).hasEntities())
{
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_siege_workshop", { "militaryBase": true }));
return;
}
@ -1832,10 +1830,7 @@ m.HQ.prototype.constructTrainingBuildings = function(gameState, queues)
if (!template)
continue;
if (template.hasDefensiveFire() || template.trainableEntities())
{
let metadata = { "preferredBase": this.findBestBaseForMilitary(gameState) };
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, advanced, metadata));
}
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, advanced, { "militaryBase": true }));
else // not a military building, but still use this queue
queues.militaryBuilding.addPlan(new m.ConstructionPlan(gameState, advanced));
return;
@ -1844,23 +1839,32 @@ m.HQ.prototype.constructTrainingBuildings = function(gameState, queues)
};
/**
* Construct military building in bases nearest to the ennemies TODO revisit as the nearest one may not be accessible
* Find base nearest to ennemies for military buildings.
*/
m.HQ.prototype.findBestBaseForMilitary = function(gameState)
{
let ccEnts = gameState.updatingGlobalCollection("allCCs", API3.Filters.byClass("CivCentre")).toEntityArray();
let bestBase = 1;
let bestBase;
let enemyFound = false;
let distMin = Math.min();
for (let cce of ccEnts)
{
if (gameState.isPlayerAlly(cce.owner()))
continue;
if (enemyFound && !gameState.isPlayerEnemy(cce.owner()))
continue;
let access = m.getLandAccess(gameState, cce);
let isEnemy = gameState.isPlayerEnemy(cce.owner());
for (let cc of ccEnts)
{
if (cc.owner() != PlayerID)
continue;
if (m.getLandAccess(gameState, cc) != access)
continue;
let dist = API3.SquareVectorDistance(cc.position(), cce.position());
if (dist > distMin)
if (!enemyFound && isEnemy)
enemyFound = true;
else if (dist > distMin)
continue;
bestBase = cc.getMetadata(PlayerID, "base");
distMin = dist;
@ -2449,7 +2453,8 @@ m.HQ.prototype.update = function(gameState, queues, events)
this.garrisonManager.update(gameState, events);
this.defenseManager.update(gameState, events);
this.constructTrainingBuildings(gameState, queues);
if (gameState.ai.playedTurn % 3 == 0)
this.constructTrainingBuildings(gameState, queues);
if (this.Config.difficulty > 0)
this.buildDefenses(gameState, queues);

View file

@ -109,10 +109,11 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
if (template.buildPlacementType() === "shore")
return this.findDockPosition(gameState);
let HQ = gameState.ai.HQ;
if (template.hasClass("Storehouse") && this.metadata.base)
{
// recompute the best dropsite location in case some conditions have changed
let base = gameState.ai.HQ.getBaseByID(this.metadata.base);
let base = HQ.getBaseByID(this.metadata.base);
let type = this.metadata.type ? this.metadata.type : "wood";
let newpos = base.findBestDropsiteLocation(gameState, type);
if (newpos && newpos.quality > 0)
@ -130,10 +131,10 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
if (this.metadata && this.metadata.resource)
{
let proximity = this.metadata.proximity ? this.metadata.proximity : undefined;
pos = gameState.ai.HQ.findEconomicCCLocation(gameState, template, this.metadata.resource, proximity);
pos = HQ.findEconomicCCLocation(gameState, template, this.metadata.resource, proximity);
}
else
pos = gameState.ai.HQ.findStrategicCCLocation(gameState, template);
pos = HQ.findStrategicCCLocation(gameState, template);
if (pos)
return { "x": pos[0], "z": pos[1], "angle": 3*Math.PI/4, "base": 0 };
@ -141,7 +142,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
}
else if (template.hasClass("DefenseTower") || template.hasClass("Fortress") || template.hasClass("ArmyCamp"))
{
let pos = gameState.ai.HQ.findDefensiveLocation(gameState, template);
let pos = HQ.findDefensiveLocation(gameState, template);
if (pos)
return { "x": pos[0], "z": pos[1], "angle": 3*Math.PI/4, "base": pos[2] };
// if this fortress is our first one, just try the standard placement
@ -150,7 +151,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
}
else if (template.hasClass("Market")) // Docks (i.e. NavalMarket) are done before
{
let pos = gameState.ai.HQ.findMarketLocation(gameState, template);
let pos = HQ.findMarketLocation(gameState, template);
if (pos && pos[2] > 0)
{
if (!this.metadata)
@ -184,17 +185,17 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
{
let base = this.metadata.base;
for (let j = 0; j < placement.map.length; ++j)
if (gameState.ai.HQ.basesMap.map[j] == base)
if (HQ.basesMap.map[j] == base)
placement.map[j] = 45;
}
else
{
for (let j = 0; j < placement.map.length; ++j)
if (gameState.ai.HQ.basesMap.map[j] !== 0)
if (HQ.basesMap.map[j] != 0)
placement.map[j] = 45;
}
if (!gameState.ai.HQ.requireHouses || !template.hasClass("House"))
if (!HQ.requireHouses || !template.hasClass("House"))
{
gameState.getOwnStructures().forEach(function(ent) {
let pos = ent.position();
@ -236,7 +237,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
{
let value = placement.map[j] - gameState.sharedScript.resourceMaps.wood.map[j]/3;
placement.map[j] = value >= 0 ? value : 0;
if (gameState.ai.HQ.borderMap.map[j] & m.fullBorder_Mask)
if (HQ.borderMap.map[j] & m.fullBorder_Mask)
placement.map[j] /= 2; // we need space around farmstead, so disfavor map border
}
}
@ -246,24 +247,24 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
// and if our first market, put it on border if possible to maximize distance with next market
let favorBorder = template.hasClass("BarterMarket");
let disfavorBorder = gameState.currentPhase() > 1 && !template.hasDefensiveFire();
let preferredBase = this.metadata && this.metadata.preferredBase;
let militaryBase = this.metadata && this.metadata.militaryBase ? HQ.findBestBaseForMilitary(gameState) : undefined;
if (this.metadata && this.metadata.base !== undefined)
{
let base = this.metadata.base;
for (let j = 0; j < placement.map.length; ++j)
{
if (gameState.ai.HQ.basesMap.map[j] != base)
if (HQ.basesMap.map[j] != base)
placement.map[j] = 0;
else if (favorBorder && gameState.ai.HQ.borderMap.map[j] & m.border_Mask)
placement.map[j] += 50;
else if (disfavorBorder && !(gameState.ai.HQ.borderMap.map[j] & m.fullBorder_Mask) && placement.map[j] > 0)
placement.map[j] += 10;
if (placement.map[j] > 0)
else if (placement.map[j] > 0)
{
if (favorBorder && HQ.borderMap.map[j] & m.border_Mask)
placement.map[j] += 50;
else if (disfavorBorder && !(HQ.borderMap.map[j] & m.fullBorder_Mask))
placement.map[j] += 10;
let x = (j % placement.width + 0.5) * cellSize;
let z = (Math.floor(j / placement.width) + 0.5) * cellSize;
if (gameState.ai.HQ.isNearInvadingArmy([x, z]))
if (HQ.isNearInvadingArmy([x, z]))
placement.map[j] = 0;
}
}
@ -272,22 +273,21 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
{
for (let j = 0; j < placement.map.length; ++j)
{
if (gameState.ai.HQ.basesMap.map[j] === 0)
if (HQ.basesMap.map[j] == 0)
placement.map[j] = 0;
else if (favorBorder && gameState.ai.HQ.borderMap.map[j] & m.border_Mask)
placement.map[j] += 50;
else if (disfavorBorder && !(gameState.ai.HQ.borderMap.map[j] & m.fullBorder_Mask) && placement.map[j] > 0)
placement.map[j] += 10;
if (preferredBase && gameState.ai.HQ.basesMap.map[j] == this.metadata.preferredBase)
placement.map[j] += 200;
if (placement.map[j] > 0)
else if (placement.map[j] > 0)
{
if (favorBorder && HQ.borderMap.map[j] & m.border_Mask)
placement.map[j] += 50;
else if (disfavorBorder && !(HQ.borderMap.map[j] & m.fullBorder_Mask))
placement.map[j] += 10;
let x = (j % placement.width + 0.5) * cellSize;
let z = (Math.floor(j / placement.width) + 0.5) * cellSize;
if (gameState.ai.HQ.isNearInvadingArmy([x, z]))
if (HQ.isNearInvadingArmy([x, z]))
placement.map[j] = 0;
else if (militaryBase && HQ.basesMap.map[j] == militaryBase)
placement.map[j] += 200;
}
}
}
@ -333,7 +333,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
let territorypos = placement.gamePosToMapPos([x, z]);
let territoryIndex = territorypos[0] + territorypos[1]*placement.width;
// default angle = 3*Math.PI/4;
return { "x": x, "z": z, "angle": 3*Math.PI/4, "base": gameState.ai.HQ.basesMap.map[territoryIndex] };
return { "x": x, "z": z, "angle": 3*Math.PI/4, "base": HQ.basesMap.map[territoryIndex] };
};
/**