1
1
forked from 0ad/0ad

Changes in AI: Decrease a bit the required number of champions in attacks because of the recent increase of their cost,

Make more use of corrals when no fields and Cleanups

This was SVN commit r18216.
This commit is contained in:
mimo 2016-05-21 17:06:25 +00:00
parent 682086b7fb
commit 9c9796d8ad
13 changed files with 96 additions and 97 deletions

View File

@ -7,7 +7,7 @@ m.EntityCollection = function(sharedAI, entities = new Map(), filters = [])
this._entities = entities;
this._filters = filters;
this.dynamicProp = [];
for (var filter of this._filters)
for (let filter of this._filters)
if (filter.dynamicProperties.length)
this.dynamicProp = this.dynamicProp.concat(filter.dynamicProperties);
@ -21,8 +21,8 @@ m.EntityCollection = function(sharedAI, entities = new Map(), filters = [])
m.EntityCollection.prototype.Serialize = function()
{
var filters = [];
for (var f of this._filters)
let filters = [];
for (let f of this._filters)
filters.push(uneval(f));
return {
"ents": this.toIdArray(),
@ -54,6 +54,7 @@ m.EntityCollection.prototype.freeze = function()
{
this.frozen = true;
};
m.EntityCollection.prototype.defreeze = function()
{
this.frozen = false;
@ -84,7 +85,7 @@ m.EntityCollection.prototype.filter = function(filter, thisp)
if (typeof filter === "function")
filter = {"func": filter, "dynamicProperties": []};
var ret = new Map();
let ret = new Map();
for (let [id, ent] of this._entities)
if (filter.func.call(thisp, ent, id, this))
ret.set(id, ent);
@ -98,7 +99,7 @@ m.EntityCollection.prototype.filter = function(filter, thisp)
m.EntityCollection.prototype.filterNearest = function(targetPos, n)
{
// Compute the distance of each entity
var data = []; // [ [id, ent, distance], ... ]
let data = []; // [ [id, ent, distance], ... ]
for (let [id, ent] of this._entities)
if (ent.position())
data.push([id, ent, m.SquareVectorDistance(targetPos, ent.position())]);
@ -121,7 +122,7 @@ m.EntityCollection.prototype.filterNearest = function(targetPos, n)
m.EntityCollection.prototype.filter_raw = function(callback, thisp)
{
var ret = new Map();
let ret = new Map();
for (let [id, ent] of this._entities)
{
let val = ent._entity;
@ -177,9 +178,8 @@ m.EntityCollection.prototype.destroy = function()
return this;
};
m.EntityCollection.prototype.attack = function(unit)
m.EntityCollection.prototype.attack = function(unitId)
{
var unitId = unit;
Engine.PostCommand(PlayerID,{"type": "attack", "entities": this.toIdArray(), "target": unitId, "queued": false});
return this;
};
@ -194,8 +194,8 @@ m.EntityCollection.prototype.setStance = function(stance)
// Returns the average position of all units
m.EntityCollection.prototype.getCentrePosition = function()
{
var sumPos = [0, 0];
var count = 0;
let sumPos = [0, 0];
let count = 0;
for (let ent of this._entities.values())
{
if (!ent.position())
@ -213,8 +213,8 @@ m.EntityCollection.prototype.getCentrePosition = function()
// always a risk that it'll be unprecise.
m.EntityCollection.prototype.getApproximatePosition = function(sample)
{
var sumPos = [0, 0];
var i = 0;
let sumPos = [0, 0];
let i = 0;
for (let ent of this._entities.values())
{
if (!ent.position())
@ -255,8 +255,8 @@ m.EntityCollection.prototype.addEnt = function(ent)
// But can remove one.
m.EntityCollection.prototype.updateEnt = function(ent, force)
{
var passesFilters = true;
for (var filter of this._filters)
let passesFilters = true;
for (let filter of this._filters)
passesFilters = passesFilters && filter.func(ent);
if (passesFilters)

View File

@ -53,7 +53,7 @@ m.Filters = {
byHasMetadata: function(player, key){
return {"func" : function(ent){
return ent.getMetadata(player, key) != undefined;
return ent.getMetadata(player, key) !== undefined;
},
"dynamicProperties": ['metadata.' + key]};
},
@ -212,26 +212,22 @@ m.Filters = {
byResource: function(resourceType){
return {"func" : function(ent){
var type = ent.resourceSupplyType();
if (!ent.resourceSupplyMax())
return false;
let type = ent.resourceSupplyType();
if (!type)
return false;
var amount = ent.resourceSupplyMax();
if (!amount)
return false;
// Skip targets that are too hard to hunt
if (!ent.isHuntable())
if (!ent.isHuntable() || ent.hasClass("SeaCreature"))
return false;
// And don't go for the bloody fish! TODO: better accessibility checks
if (ent.hasClass("SeaCreature"))
return false;
// Don't go for floating treasures since we won't be able to reach them and it kills the pathfinder.
if (ent.templateName() == "other/special_treasure_shipwreck_debris" ||
ent.templateName() == "other/special_treasure_shipwreck" )
ent.templateName() == "other/special_treasure_shipwreck" )
return false;
if (type.generic == "treasure")
return resourceType == type.specific;
@ -244,8 +240,7 @@ m.Filters = {
return {"func" : function(ent){
if (!ent.hasClass("Animal"))
return false;
var amount = ent.resourceSupplyMax();
if (!amount)
if (!ent.resourceSupplyMax())
return false;
// Skip targets that are too hard to hunt
if (!ent.isHuntable())

View File

@ -412,7 +412,7 @@ m.Map.prototype.getNonObstructedTile = function(i, radius, obstruction)
m.Map.prototype.isObstructedTile = function(kx, ky, radius)
{
let w = this.width;
if (kx < radius || kx >= w - radius || ky < radius || ky >= w - radius || this.map[kx+ky*w] == 0)
if (kx < radius || kx >= w - radius || ky < radius || ky >= w - radius || this.map[kx+ky*w] === 0)
return true;
for (let dy = 0; dy <= radius; ++dy)
{
@ -420,7 +420,7 @@ m.Map.prototype.isObstructedTile = function(kx, ky, radius)
let xp = kx + (ky + dy)*w;
let xm = kx + (ky - dy)*w;
for (let dx = -dxmax; dx <= dxmax; ++dx)
if (this.map[xp + dx] == 0 || this.map[xm + dx] == 0)
if (this.map[xp + dx] === 0 || this.map[xm + dx] === 0)
return true;
}
return false;

View File

@ -52,7 +52,7 @@ m.SharedScript.prototype.Deserialize = function(data)
this._techTemplates = data.techTp;
this._techModifications = data.techModifications;
this._entityMetadata = data.metadata;
this._derivedTemplates = {};
this._derivedTemplates = {};
this.isDeserialized = true;
};
@ -138,11 +138,11 @@ m.SharedScript.prototype.init = function(state, deserialization)
this.barterPrices = state.barterPrices;
this.passabilityMap = state.passabilityMap;
if (this.mapSize % this.passabilityMap.width != 0)
if (this.mapSize % this.passabilityMap.width !== 0)
error("AI shared component inconsistent sizes: map=" + this.mapSize + " while passability=" + this.passabilityMap.width);
this.passabilityMap.cellSize = this.mapSize / this.passabilityMap.width;
this.territoryMap = state.territoryMap;
if (this.mapSize % this.territoryMap.width != 0)
if (this.mapSize % this.territoryMap.width !== 0)
error("AI shared component inconsistent sizes: map=" + this.mapSize + " while territory=" + this.territoryMap.width);
this.territoryMap.cellSize = this.mapSize / this.territoryMap.width;
@ -425,13 +425,16 @@ m.SharedScript.prototype.deleteMetadata = function(player, ent, key)
return true;
};
m.copyPrototype = function(descendant, parent) {
var sConstructor = parent.toString();
var aMatch = sConstructor.match( /\s*function (.*)\(/ );
if ( aMatch != null ) { descendant.prototype[aMatch[1]] = parent; }
for (var m in parent.prototype) {
descendant.prototype[m] = parent.prototype[m];
}
m.copyPrototype = function(descendant, parent)
{
var sConstructor = parent.toString();
var aMatch = sConstructor.match( /\s*function (.*)\(/ );
if ( aMatch != null )
descendant.prototype[aMatch[1]] = parent;
for (let p in parent.prototype)
descendant.prototype[p] = parent.prototype[p];
};
return m;

View File

@ -124,21 +124,21 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data)
{
priority = 90;
// basically we want a mix of citizen soldiers so our barracks have a purpose, and champion units.
this.unitStat.RangedInfantry = { "priority": 0.7, "minSize": 5, "targetSize": 15, "batchSize": 5, "classes": ["Infantry","Ranged", "CitizenSoldier"],
this.unitStat.RangedInfantry = { "priority": 0.7, "minSize": 5, "targetSize": 20, "batchSize": 5, "classes": ["Infantry", "Ranged", "CitizenSoldier"],
"interests": [["strength",3], ["cost",1] ] };
this.unitStat.MeleeInfantry = { "priority": 0.7, "minSize": 5, "targetSize": 15, "batchSize": 5, "classes": ["Infantry","Melee", "CitizenSoldier"],
this.unitStat.MeleeInfantry = { "priority": 0.7, "minSize": 5, "targetSize": 20, "batchSize": 5, "classes": ["Infantry", "Melee", "CitizenSoldier"],
"interests": [ ["strength",3], ["cost",1] ] };
this.unitStat.ChampRangedInfantry = { "priority": 1, "minSize": 5, "targetSize": 25, "batchSize": 5, "classes": ["Infantry","Ranged", "Champion"],
this.unitStat.ChampRangedInfantry = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "classes": ["Infantry", "Ranged", "Champion"],
"interests": [["strength",3], ["cost",1] ] };
this.unitStat.ChampMeleeInfantry = { "priority": 1, "minSize": 5, "targetSize": 20, "batchSize": 5, "classes": ["Infantry","Melee", "Champion"],
this.unitStat.ChampMeleeInfantry = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "classes": ["Infantry", "Melee", "Champion"],
"interests": [ ["strength",3], ["cost",1] ] };
this.unitStat.MeleeCavalry = { "priority": 0.7, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry","Melee", "CitizenSoldier"],
this.unitStat.RangedCavalry = { "priority": 0.7, "minSize": 4, "targetSize": 20, "batchSize": 4, "classes": ["Cavalry", "Ranged", "CitizenSoldier"],
"interests": [ ["strength",2], ["cost",1] ] };
this.unitStat.RangedCavalry = { "priority": 0.7, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry","Ranged", "CitizenSoldier"],
this.unitStat.MeleeCavalry = { "priority": 0.7, "minSize": 4, "targetSize": 20, "batchSize": 4, "classes": ["Cavalry", "Melee", "CitizenSoldier"],
"interests": [ ["strength",2], ["cost",1] ] };
this.unitStat.ChampMeleeInfantry = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "classes": ["Infantry","Melee", "Champion"],
this.unitStat.ChampRangedCavalry = { "priority": 1, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry", "Ranged", "Champion"],
"interests": [ ["strength",3], ["cost",1] ] };
this.unitStat.ChampMeleeCavalry = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "classes": ["Cavalry","Melee", "Champion"],
this.unitStat.ChampMeleeCavalry = { "priority": 1, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry", "Melee", "Champion"],
"interests": [ ["strength",2], ["cost",1] ] };
this.unitStat.Hero = { "priority": 1, "minSize": 0, "targetSize": 1, "batchSize": 1, "classes": ["Hero"],
"interests": [ ["strength",2], ["cost",1] ] };

View File

@ -756,7 +756,7 @@ m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
var idleBuilderWorkers = builderWorkers.filter(API3.Filters.isIdle());
// if we're constructing and we have the foundations to our base anchor, only try building that.
if (this.constructing == true && this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(), API3.Filters.byMetadata(PlayerID, "baseAnchor", true))).length != 0)
if (this.constructing === true && this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(), API3.Filters.byMetadata(PlayerID, "baseAnchor", true))).hasEntities())
{
foundations = this.buildings.filter(API3.Filters.byMetadata(PlayerID, "baseAnchor", true)).toEntityArray();
let tID = foundations[0].id();
@ -813,7 +813,7 @@ m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
targetNB = 4;
else if (target.hasClass("Fortress"))
targetNB = 7;
if (target.getMetadata(PlayerID, "baseAnchor") == true || (target.hasClass("Wonder") && gameState.getGameType() === "wonder"))
if (target.getMetadata(PlayerID, "baseAnchor") === true || (target.hasClass("Wonder") && gameState.getGameType() === "wonder"))
{
targetNB = 15;
maxTotalBuilders = Math.max(maxTotalBuilders, 15);
@ -898,7 +898,7 @@ m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair)
let targetNB = 1;
if (target.hasClass("Fortress"))
targetNB = 3;
if (target.getMetadata(PlayerID, "baseAnchor") == true || (target.hasClass("Wonder") && gameState.getGameType() === "wonder"))
if (target.getMetadata(PlayerID, "baseAnchor") === true || (target.hasClass("Wonder") && gameState.getGameType() === "wonder"))
{
maxTotalBuilders = Math.ceil(workers.length * 0.3);
targetNB = 5;

View File

@ -174,7 +174,7 @@ m.HQ.prototype.checkEvents = function (gameState, events, queues)
if (!ent || !ent.isOwn(PlayerID))
continue;
if (ent.getMetadata(PlayerID, "baseAnchor") == true)
if (ent.getMetadata(PlayerID, "baseAnchor") === true)
{
let base = this.getBaseByID(ent.getMetadata(PlayerID, "base"));
if (base.constructing)
@ -426,7 +426,7 @@ m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
var numberOfWorkers = 0; // all workers
var numberOfSupports = 0; // only support workers (i.e. non fighting)
gameState.getOwnUnits().forEach (function (ent) {
if (ent.getMetadata(PlayerID, "role") == "worker" && ent.getMetadata(PlayerID, "plan") == undefined)
if (ent.getMetadata(PlayerID, "role") === "worker" && ent.getMetadata(PlayerID, "plan") === undefined)
{
++numberOfWorkers;
if (ent.hasClass("Support"))
@ -437,7 +437,7 @@ m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
gameState.getOwnTrainingFacilities().forEach(function(ent) {
ent.trainingQueue().forEach(function(item) {
numberInTraining += item.count;
if (item.metadata && item.metadata.role && item.metadata.role == "worker" && item.metadata.plan == undefined)
if (item.metadata && item.metadata.role && item.metadata.role === "worker" && item.metadata.plan === undefined)
{
numberOfWorkers += item.count;
if (item.metadata.support)
@ -1043,9 +1043,9 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
for (let j = 0; j < this.territoryMap.length; ++j)
{
// do not try on the border of our territory
if (this.frontierMap.map[j] == 2)
if (this.frontierMap.map[j] === 2)
continue;
if (this.basesMap.map[j] == 0) // only in our territory
if (this.basesMap.map[j] === 0) // only in our territory
continue;
// with enough room around to build the cc
let i = this.territoryMap.getNonObstructedTile(j, radius, obstructions);
@ -1154,12 +1154,12 @@ m.HQ.prototype.findDefensiveLocation = function(gameState, template)
if (!wonderMode)
{
// do not try if well inside or outside territory
if (this.frontierMap.map[j] == 0)
if (this.frontierMap.map[j] === 0)
continue;
if (this.frontierMap.map[j] == 1 && isTower)
if (this.frontierMap.map[j] === 1 && isTower)
continue;
}
if (this.basesMap.map[j] == 0) // inaccessible cell
if (this.basesMap.map[j] === 0) // inaccessible cell
continue;
// with enough room around to build the cc
var i = this.territoryMap.getNonObstructedTile(j, radius, obstructions);
@ -1303,12 +1303,17 @@ 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).hasEntities())
let nCorral = gameState.getOwnEntitiesByClass("Corral", true).length;
if (nCorral === 0 ||
(gameState.isDisabledTemplates(gameState.applyCiv("structures/{civ}_field")) &&
nCorral < gameState.currentPhase() && gameState.getPopulation() > 30*nCorral))
{
if (this.canBuild(gameState, "structures/{civ}_corral"))
{
queues.corral.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_corral"));
return;
return;
}
if (nCorral === 0) return;
}
// And train some animals
@ -1327,7 +1332,7 @@ m.HQ.prototype.manageCorral = function(gameState, queues)
let count = gameState.countEntitiesByType(trainable, true);
for (let item of corral.trainingQueue())
count += item.count;
if (count > 1)
if (count > nCorral)
continue;
queues.corral.addPlan(new m.TrainingPlan(gameState, trainable, { "trainer": corral.id() }));
return;
@ -1839,7 +1844,7 @@ m.HQ.prototype.updateTerritories = function(gameState)
continue;
if (this.territoryMap.getOwnerIndex(j) != PlayerID)
{
if (this.basesMap.map[j] == 0)
if (this.basesMap.map[j] === 0)
continue;
let base = this.getBaseByID(this.basesMap.map[j]);
let index = base.territoryIndices.indexOf(j);
@ -1851,7 +1856,7 @@ m.HQ.prototype.updateTerritories = function(gameState)
base.territoryIndices.splice(index, 1);
this.basesMap.map[j] = 0;
}
else if (this.basesMap.map[j] == 0)
else if (this.basesMap.map[j] === 0)
{
let landPassable = false;
let ind = API3.getMapIndices(j, this.territoryMap, passabilityMap);

View File

@ -45,7 +45,7 @@ m.createObstructionMap = function(gameState, accessIndex, template)
{
let tilePlayer = (territoryMap.data[k] & m.TERRITORY_PLAYER_MASK);
let isConnected = (territoryMap.data[k] & m.TERRITORY_BLINKING_MASK) == 0;
if (tilePlayer == PlayerID)
if (tilePlayer === PlayerID)
{
if (!buildOwn || !buildNeutral && !isConnected)
continue;
@ -55,7 +55,7 @@ m.createObstructionMap = function(gameState, accessIndex, template)
if (!buildAlly || !buildNeutral && !isConnected)
continue;
}
else if (tilePlayer == 0)
else if (tilePlayer === 0)
{
if (!buildNeutral)
continue;

View File

@ -42,7 +42,6 @@ m.Queue.prototype.check= function(gameState)
return;
this.plans.shift();
}
return;
};
m.Queue.prototype.getNext = function()

View File

@ -148,7 +148,7 @@ m.QueueManager.prototype.printQueues = function(gameState)
{
var numWorkers = 0;
gameState.getOwnUnits().forEach (function (ent) {
if (ent.getMetadata(PlayerID, "role") == "worker" && ent.getMetadata(PlayerID, "plan") == undefined)
if (ent.getMetadata(PlayerID, "role") === "worker" && ent.getMetadata(PlayerID, "plan") === undefined)
numWorkers++;
});
API3.warn("---------- QUEUES ------------ with pop " + gameState.getPopulation() + " and workers " + numWorkers);

View File

@ -18,9 +18,6 @@ m.ConstructionPlan = function(gameState, type, metadata, position)
m.ConstructionPlan.prototype = Object.create(m.QueuePlan.prototype);
// checks other than resource ones.
// TODO: change this.
// TODO: if there are specific requirements here, maybe try to do them?
m.ConstructionPlan.prototype.canStart = function(gameState)
{
if (gameState.ai.HQ.turnCache.buildingBuilt) // do not start another building if already one this turn
@ -51,7 +48,8 @@ m.ConstructionPlan.prototype.start = function(gameState)
Engine.ProfileStop();
return;
}
else if (this.metadata && this.metadata.expectedGain)
if (this.metadata && this.metadata.expectedGain)
{
// Check if this market is still worth building (others may have been built making it useless)
let tradeManager = gameState.ai.HQ.tradeManager;
@ -93,7 +91,7 @@ m.ConstructionPlan.prototype.start = function(gameState)
else // try with the lowest, move towards us unless we're same
{
for (let step = 0; step <= 1; step += 0.2)
builder.construct(this.type, (step*pos.x + (1-step)*pos.xx), (step*pos.z + (1-step)*pos.zz),
builder.construct(this.type, step*pos.x + (1-step)*pos.xx, step*pos.z + (1-step)*pos.zz,
pos.angle, this.metadata);
}
this.onStart(gameState);
@ -107,7 +105,6 @@ m.ConstructionPlan.prototype.start = function(gameState)
// TODO for dock, we should allow building them outside territory, and we should check that we are along the right sea
m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
{
var template = this.template;
if (template.buildCategory() === "Dock")
@ -146,14 +143,14 @@ 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);
if (pos)
return { "x": pos[0], "z": pos[1], "angle": 3*Math.PI/4, "base": pos[2] };
else if (template.hasClass("DefenseTower") || gameState.civ() === "mace" || gameState.civ() === "maur" ||
if (template.hasClass("DefenseTower") || gameState.civ() === "mace" || gameState.civ() === "maur" ||
gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_fortress"), true) > 0 ||
gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_army_camp"), true) > 0)
return false;
// if this fortress is our first siege unit builder, just try the standard placement as we want siege units
// if this fortress is our first siege unit builder, just try the standard placement as we want siege units
}
else if (template.hasClass("Market")) // Docks (i.e. NavalMarket) are done before
{
@ -174,7 +171,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
var placement = new API3.Map(gameState.sharedScript, "territory");
var cellSize = placement.cellSize; // size of each tile
var alreadyHasHouses = false;
if (this.position) // If a position was specified then place the building as close to it as possible
@ -197,7 +194,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
else
{
for (let j = 0; j < placement.map.length; ++j)
if (gameState.ai.HQ.basesMap.map[j] != 0)
if (gameState.ai.HQ.basesMap.map[j] !== 0)
placement.map[j] = 45;
}
@ -262,7 +259,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
placement.map[j] = 0;
else if (favorBorder && gameState.ai.HQ.borderMap.map[j] > 0)
placement.map[j] += 50;
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] == 0 && placement.map[j] > 0)
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] === 0 && placement.map[j] > 0)
placement.map[j] += 10;
if (placement.map[j] > 0)
@ -278,11 +275,11 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
{
for (let j = 0; j < placement.map.length; ++j)
{
if (gameState.ai.HQ.basesMap.map[j] == 0)
if (gameState.ai.HQ.basesMap.map[j] === 0)
placement.map[j] = 0;
else if (favorBorder && gameState.ai.HQ.borderMap.map[j] > 0)
placement.map[j] += 50;
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] == 0 && placement.map[j] > 0)
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] === 0 && placement.map[j] > 0)
placement.map[j] += 10;
if (preferredBase && gameState.ai.HQ.basesMap.map[j] == this.metadata.preferredBase)
@ -335,7 +332,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
if (bestVal <= 0)
return false;
let x = ((bestIdx % obstructions.width) + 0.5) * obstructions.cellSize;
let x = (bestIdx % obstructions.width + 0.5) * obstructions.cellSize;
let z = (Math.floor(bestIdx / obstructions.width) + 0.5) * obstructions.cellSize;
if (template.hasClass("House") || template.hasClass("Field") || template.resourceDropsiteTypes() !== undefined)
@ -343,7 +340,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
let secondBest = obstructions.findNearestObstructed(bestIdx, radius);
if (secondBest >= 0)
{
x = ((secondBest % obstructions.width) + 0.5) * obstructions.cellSize;
x = (secondBest % obstructions.width + 0.5) * obstructions.cellSize;
z = (Math.floor(secondBest / obstructions.width) + 0.5) * obstructions.cellSize;
}
}
@ -445,7 +442,7 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
if (bestIdx !== undefined && dist > bestVal + maxWater)
continue;
let x = ((i % obstructions.width) + 0.5) * obstructions.cellSize;
let x = (i % obstructions.width + 0.5) * obstructions.cellSize;
let z = (Math.floor(i / obstructions.width) + 0.5) * obstructions.cellSize;
let angle = this.getDockAngle(gameState, x, z, halfSize);
if (angle === false)
@ -476,7 +473,7 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
if (!this.metadata.proximity && bestWater < 10 && gameState.currentPhase() == 1)
return false;
var x = ((bestIdx % obstructions.width) + 0.5) * obstructions.cellSize;
var x = (bestIdx % obstructions.width + 0.5) * obstructions.cellSize;
var z = (Math.floor(bestIdx / obstructions.width) + 0.5) * obstructions.cellSize;
// Assign this dock to a base
@ -537,7 +534,7 @@ m.ConstructionPlan.prototype.getDockAngle = function(gameState, x, z, size)
let count = 0;
for (let j = 0; j < length-1; ++j)
{
if (((waterPoints[(i + j) % length]+1) % numPoints) == waterPoints[(i + j + 1) % length])
if ((waterPoints[(i + j) % length]+1) % numPoints == waterPoints[(i + j + 1) % length])
++count;
else
break;
@ -741,7 +738,7 @@ m.ConstructionPlan.prototype.getResourcesAround = function(gameState, types, i,
nbcell += weight;
}
}
if (dy == 0)
if (dy === 0)
continue;
ky = iy - dy;
if (ky >= 0 && ky < w)
@ -759,7 +756,7 @@ m.ConstructionPlan.prototype.getResourcesAround = function(gameState, types, i,
}
}
}
return nbcell ? (total / nbcell) : 0;
return nbcell ? total / nbcell : 0;
};
m.ConstructionPlan.prototype.Serialize = function()

View File

@ -519,7 +519,7 @@ 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
// and build immediately a corral if needed
if (this.needCorral)
{
template = gameState.applyCiv("structures/{civ}_corral");

View File

@ -282,7 +282,7 @@ m.Worker.prototype.startGathering = function(gameState)
continue;
// not in ennemy territory
let territoryOwner = gameState.ai.HQ.territoryMap.getOwner(supplies[i].ent.position());
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
if (territoryOwner !== 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
continue;
gameState.ai.HQ.AddTCGatherer(supplies[i].id);
ent.setMetadata(PlayerID, "supply", supplies[i].id);
@ -588,14 +588,14 @@ m.Worker.prototype.startHunting = function(gameState, position)
// Avoid ennemy territory
let territoryOwner = gameState.ai.HQ.territoryMap.getOwner(supply.position());
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
if (territoryOwner !== 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
return;
var dropsiteDist = nearestDropsiteDist(supply);
if (dropsiteDist > 35000)
return;
// Only cavalry should hunt far from dropsite (specially for non domestic animals which flee)
if (!isCavalry && (dropsiteDist > 12000 || ((dropsiteDist > 7000 || territoryOwner == 0 ) && canFlee)))
if (!isCavalry && (dropsiteDist > 12000 || ((dropsiteDist > 7000 || territoryOwner === 0 ) && canFlee)))
return;
if (dist < nearestSupplyDist)
@ -681,7 +681,7 @@ m.Worker.prototype.startFishing = function(gameState)
// Avoid ennemy territory
let territoryOwner = gameState.ai.HQ.territoryMap.getOwner(supply.position());
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
if (territoryOwner !== 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
return;
var dropsiteDist = nearestDropsiteDist(supply);