ai cleanup

This was SVN commit r18290.
This commit is contained in:
mimo 2016-06-02 18:08:14 +00:00
parent d9caf157e2
commit 5be948019b
11 changed files with 176 additions and 163 deletions

View file

@ -6,21 +6,17 @@ var API3 = function(m)
*/
m.Class = function(data)
{
var ctor;
let ctor;
if (data._init)
ctor = data._init;
else
ctor = function() { };
if (data._super)
{
ctor.prototype = { "__proto__": data._super.prototype };
}
for (var key in data)
{
for (let key in data)
ctor.prototype[key] = data[key];
}
return ctor;
};

View file

@ -1,7 +1,6 @@
var API3 = function(m)
{
/**
* Provides an API for the rest of the AI scripts to query the world state at a
* higher level than the raw data.
@ -183,14 +182,14 @@ m.GameState.prototype.isResearched = function(template)
return this.playerData.researchedTechs[template] !== undefined;
};
// true if started or queued
/** true if started or queued */
m.GameState.prototype.isResearching = function(template)
{
return this.playerData.researchStarted[template] !== undefined ||
this.playerData.researchQueued[template] !== undefined;
};
// this is an "in-absolute" check that doesn't check if we have a building to research from.
/** this is an "in-absolute" check that doesn't check if we have a building to research from. */
m.GameState.prototype.canResearch = function(techTemplateName, noRequirementCheck)
{
let template = this.getTemplate(techTemplateName);
@ -227,8 +226,10 @@ m.GameState.prototype.canResearch = function(techTemplateName, noRequirementChec
return this.checkTechRequirements(template.requirements());
};
// Private function for checking a set of requirements is met
// basically copies TechnologyManager's
/**
* Private function for checking a set of requirements is met
* basically copies TechnologyManager
*/
m.GameState.prototype.checkTechRequirements = function(reqs)
{
// If there are no requirements then all requirements are met
@ -447,7 +448,7 @@ m.GameState.prototype.getEnemyUnits = function(enemyID)
return this.updatingGlobalCollection("" + enemyID + "-units", m.Filters.byClass("Unit"), this.getEnemyEntities(enemyID));
};
// if maintain is true, this will be stored. Otherwise it's one-shot.
/** if maintain is true, this will be stored. Otherwise it's one-shot. */
m.GameState.prototype.getOwnEntitiesByMetadata = function(key, value, maintain)
{
if (maintain === true)
@ -599,7 +600,7 @@ m.GameState.prototype.getFishableSupplies = function()
return this.updatingGlobalCollection("resource-fish", m.Filters.isFishable(), this.getEntities());
};
// This returns only units from buildings.
/** This returns only units from buildings. */
m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
{
let allTrainable = [];
@ -653,9 +654,11 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
return ret;
};
// Return all techs which can currently be researched
// Does not factor cost.
// If there are pairs, both techs are returned.
/**
* Return all techs which can currently be researched
* Does not factor cost.
* If there are pairs, both techs are returned.
*/
m.GameState.prototype.findAvailableTech = function()
{
let allResearchable = [];
@ -790,7 +793,7 @@ m.GameState.prototype.isDisabledTemplates = function(template)
return this.playerData.disabledTemplates[template];
};
// Checks whether the maximum number of buildings have been cnstructed for a certain catergory
/** Checks whether the maximum number of buildings have been constructed for a certain catergory */
m.GameState.prototype.isEntityLimitReached = function(category)
{
if (this.playerData.entityLimits[category] === undefined ||

View file

@ -231,12 +231,12 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
{
Engine.ProfileStart("Shared ApplyEntitiesDelta");
var foundationFinished = {};
let foundationFinished = {};
// by order of updating:
// we "Destroy" last because we want to be able to switch Metadata first.
var CreateEvents = state.events.Create;
let CreateEvents = state.events.Create;
for (let i = 0; i < CreateEvents.length; ++i)
{
let evt = CreateEvents[i];
@ -289,7 +289,7 @@ m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
this.setMetadata(evt.owner, this._entities.get(evt.id), key, evt.metadata[key]);
}
var DestroyEvents = state.events.Destroy;
let DestroyEvents = state.events.Destroy;
for (let i = 0; i < DestroyEvents.length; ++i)
{
let evt = DestroyEvents[i];
@ -404,7 +404,7 @@ m.SharedScript.prototype.updateEntityCollections = function(property, ent)
m.SharedScript.prototype.setMetadata = function(player, ent, key, value)
{
var metadata = this._entityMetadata[player][ent.id()];
let metadata = this._entityMetadata[player][ent.id()];
if (!metadata)
metadata = this._entityMetadata[player][ent.id()] = {};
metadata[key] = value;
@ -415,7 +415,7 @@ m.SharedScript.prototype.setMetadata = function(player, ent, key, value)
m.SharedScript.prototype.getMetadata = function(player, ent, key)
{
var metadata = this._entityMetadata[player][ent.id()];
let metadata = this._entityMetadata[player][ent.id()];
if (!metadata || !(key in metadata))
return undefined;
@ -424,7 +424,7 @@ m.SharedScript.prototype.getMetadata = function(player, ent, key)
m.SharedScript.prototype.deleteMetadata = function(player, ent, key)
{
var metadata = this._entityMetadata[player][ent.id()];
let metadata = this._entityMetadata[player][ent.id()];
if (!metadata || !(key in metadata))
return true;
@ -437,8 +437,8 @@ m.SharedScript.prototype.deleteMetadata = function(player, ent, key)
m.copyPrototype = function(descendant, parent)
{
var sConstructor = parent.toString();
var aMatch = sConstructor.match( /\s*function (.*)\(/ );
let sConstructor = parent.toString();
let aMatch = sConstructor.match( /\s*function (.*)\(/ );
if ( aMatch != null )
descendant.prototype[aMatch[1]] = parent;

View file

@ -23,8 +23,10 @@ m.SquareVectorDistance = function(a, b)
return dx*dx + dz*dz;
};
// A is the reference, B must be in "range" of A
// this supposes the range is already squared
/**
* A is the reference, B must be in "range" of A
* this supposes the range is already squared
*/
m.inRange = function(a, b, range)// checks for X distance
{
// will avoid unnecessary checking for position in some rare cases... I'm lazy
@ -36,7 +38,7 @@ m.inRange = function(a, b, range)// checks for X distance
return dx*dx + dz*dz < range;
};
// slower than SquareVectorDistance, faster than VectorDistance but not exactly accurate.
/** Slower than SquareVectorDistance, faster than VectorDistance but not exactly accurate. */
m.ManhattanDistance = function(a, b)
{
let dx = a[0] - b[0];
@ -61,7 +63,7 @@ m.PickRandom = function(list)
// Utility functions for conversions of maps of different sizes
/**
*return the index of map2 with max content from indices contained inside the cell i of map1
* Returns the index of map2 with max content from indices contained inside the cell i of map1
* map1.cellSize must be a multiple of map2.cellSize
*/
m.getMaxMapIndex = function(i, map1, map2)
@ -78,7 +80,7 @@ m.getMaxMapIndex = function(i, map1, map2)
};
/**
* return the list of indices of map2 contained inside the cell i of map1
* Returns the list of indices of map2 contained inside the cell i of map1
* map1.cellSize must be a multiple of map2.cellSize
*/
m.getMapIndices = function(i, map1, map2)
@ -94,7 +96,7 @@ m.getMapIndices = function(i, map1, map2)
};
/**
* return the list of points of map2 contained inside the cell i of map1
* Returns the list of points of map2 contained inside the cell i of map1
* map1.cellSize must be a multiple of map2.cellSize
*/
m.getMapPoints = function(i, map1, map2)

View file

@ -1,7 +1,7 @@
var PETRA = function(m)
{
// Specialization of Armies used by the defense manager.
/** Specialization of Armies used by the defense manager. */
m.DefenseArmy = function(gameState, ownEntities, foeEntities)
{
if (!m.Army.call(this, gameState, ownEntities, foeEntities))
@ -17,17 +17,17 @@ m.DefenseArmy.prototype.assignUnit = function (gameState, entID)
// we'll assume this defender is ours already.
// we'll also override any previous assignment
var ent = gameState.getEntityById(entID);
let ent = gameState.getEntityById(entID);
if (!ent || !ent.position())
return false;
// try to return its resources, and if any, the attack order will be queued
var queued = m.returnResources(gameState, ent);
let queued = m.returnResources(gameState, ent);
var idMin;
var distMin;
var idMinAll;
var distMinAll;
let idMin;
let distMin;
let idMinAll;
let distMinAll;
for (let id of this.foeEntities)
{
let eEnt = gameState.getEntityById(id);
@ -84,7 +84,6 @@ m.DefenseArmy.prototype.assignUnit = function (gameState, entID)
return true;
};
// TODO: this should return cleverer results ("needs anti-elephant"…)
m.DefenseArmy.prototype.needsDefenders = function (gameState)
{
// some preliminary checks because we don't update for tech so entStrength removed can be > entStrength added

View file

@ -397,34 +397,34 @@ m.HQ.prototype.checkEvents = function (gameState, events, queues)
}
};
// Called by the "town phase" research plan once it's started
/** Called by the "town phase" research plan once it's started */
m.HQ.prototype.OnTownPhase = function(gameState)
{
var phaseName = gameState.getTemplate(gameState.townPhase()).name();
let phaseName = gameState.getTemplate(gameState.townPhase()).name();
m.chatNewPhase(gameState, phaseName, true);
};
// Called by the "city phase" research plan once it's started
/** Called by the "city phase" research plan once it's started */
m.HQ.prototype.OnCityPhase = function(gameState)
{
// increase the priority of defense buildings to free this queue for our first fortress
gameState.ai.queueManager.changePriority("defenseBuilding", 2*this.Config.priorities.defenseBuilding);
var phaseName = gameState.getTemplate(gameState.cityPhase()).name();
let phaseName = gameState.getTemplate(gameState.cityPhase()).name();
m.chatNewPhase(gameState, phaseName, true);
};
// This code trains citizen workers, trying to keep close to a ratio of worker/soldiers
/** This code trains citizen workers, trying to keep close to a ratio of worker/soldiers */
m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
{
// default template
var requirementsDef = [["cost", 1], ["costsResource", 1, "food"]];
var classesDef = ["Support", "Worker"];
var templateDef = this.findBestTrainableUnit(gameState, classesDef, requirementsDef);
let requirementsDef = [["cost", 1], ["costsResource", 1, "food"]];
let classesDef = ["Support", "Worker"];
let templateDef = this.findBestTrainableUnit(gameState, classesDef, requirementsDef);
// counting the workers that aren't part of a plan
var numberOfWorkers = 0; // all workers
var numberOfSupports = 0; // only support workers (i.e. non fighting)
let numberOfWorkers = 0; // all workers
let 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)
{
@ -433,9 +433,10 @@ m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
++numberOfSupports;
}
});
var numberInTraining = 0;
let numberInTraining = 0;
gameState.getOwnTrainingFacilities().forEach(function(ent) {
ent.trainingQueue().forEach(function(item) {
for (let item of ent.trainingQueue())
{
numberInTraining += item.count;
if (item.metadata && item.metadata.role && item.metadata.role === "worker" && item.metadata.plan === undefined)
{
@ -443,14 +444,14 @@ m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
if (item.metadata.support)
numberOfSupports += item.count;
}
});
}
});
// Anticipate the optimal batch size when this queue will start
// and adapt the batch size of the first and second queued workers to the present population
// to ease a possible recovery if our population was drastically reduced by an attack
// (need to go up to second queued as it is accounted in queueManager)
var size = numberOfWorkers < 12 ? 1 : Math.min(5, Math.ceil(numberOfWorkers / 10));
let size = numberOfWorkers < 12 ? 1 : Math.min(5, Math.ceil(numberOfWorkers / 10));
if (queues.villager.plans[0])
{
queues.villager.plans[0].number = Math.min(queues.villager.plans[0].number, size);
@ -464,10 +465,10 @@ m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
queues.citizenSoldier.plans[1].number = Math.min(queues.citizenSoldier.plans[1].number, size);
}
var numberOfQueuedSupports = queues.villager.countQueuedUnits();
var numberOfQueuedSoldiers = queues.citizenSoldier.countQueuedUnits();
var numberQueued = numberOfQueuedSupports + numberOfQueuedSoldiers;
var numberTotal = numberOfWorkers + numberQueued;
let numberOfQueuedSupports = queues.villager.countQueuedUnits();
let numberOfQueuedSoldiers = queues.citizenSoldier.countQueuedUnits();
let numberQueued = numberOfQueuedSupports + numberOfQueuedSoldiers;
let numberTotal = numberOfWorkers + numberQueued;
if (this.saveResources && numberTotal > this.Config.Economy.popForTown + 10)
return;
@ -510,7 +511,7 @@ m.HQ.prototype.trainMoreWorkers = function(gameState, queues)
queues.citizenSoldier.addPlan(new m.TrainingPlan(gameState, template, { "role": "worker", "base": 0 }, size, size));
};
// picks the best template based on parameters and classes
/** picks the best template based on parameters and classes */
m.HQ.prototype.findBestTrainableUnit = function(gameState, classes, requirements)
{
var units;
@ -595,8 +596,10 @@ m.HQ.prototype.findBestTrainableUnit = function(gameState, classes, requirements
return units[0][0];
};
// returns an entity collection of workers through BaseManager.pickBuilders
// TODO: when same accessIndex, sort by distance
/**
* returns an entity collection of workers through BaseManager.pickBuilders
* TODO: when same accessIndex, sort by distance
*/
m.HQ.prototype.bulkPickWorkers = function(gameState, baseRef, number)
{
var accessIndex = baseRef.accessIndex;
@ -630,7 +633,7 @@ m.HQ.prototype.bulkPickWorkers = function(gameState, baseRef, number)
m.HQ.prototype.getTotalResourceLevel = function(gameState)
{
var total = { "food": 0, "wood": 0, "stone": 0, "metal": 0 };
let total = { "food": 0, "wood": 0, "stone": 0, "metal": 0 };
for (let base of this.baseManagers)
for (let type in total)
total[type] += base.getResourceLevel(gameState, type);
@ -665,8 +668,8 @@ m.HQ.prototype.GetCurrentGatherRates = function(gameState)
return this.currentRates;
};
/* Pick the resource which most needs another worker
/**
* Pick the resource which most needs another worker
* How this works:
* We get the rates we would want to have to be able to deal with our plans
* We get our current rates
@ -676,9 +679,9 @@ m.HQ.prototype.GetCurrentGatherRates = function(gameState)
m.HQ.prototype.pickMostNeededResources = function(gameState)
{
this.wantedRates = gameState.ai.queueManager.wantedGatherRates(gameState);
var currentRates = this.GetCurrentGatherRates(gameState);
let currentRates = this.GetCurrentGatherRates(gameState);
var needed = [];
let needed = [];
for (let res in this.wantedRates)
needed.push({ "type": res, "wanted": this.wantedRates[res], "current": currentRates[res] });
@ -693,8 +696,10 @@ m.HQ.prototype.pickMostNeededResources = function(gameState)
return needed;
};
// Returns the best position to build a new Civil Centre
// Whose primary function would be to reach new resources of type "resource".
/**
* Returns the best position to build a new Civil Centre
* Whose primary function would be to reach new resources of type "resource".
*/
m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource, proximity, fromStrategic)
{
// This builds a map. The procedure is fairly simple. It adds the resource maps
@ -868,8 +873,10 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
return [x, z];
};
// Returns the best position to build a new Civil Centre
// Whose primary function would be to assure territorial continuity with our allies
/**
* Returns the best position to build a new Civil Centre
* Whose primary function would be to assure territorial continuity with our allies
*/
m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
{
// This builds a map. The procedure is fairly simple.
@ -1008,10 +1015,12 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
return [x, z];
};
// Returns the best position to build a new market: if the allies already have a market, build it as far as possible
// from it, although not in our border to be able to defend it easily. If no allied market, our second market will
// follow the same logic
// TODO check that it is on same accessIndex
/**
* Returns the best position to build a new market: if the allies already have a market, build it as far as possible
* from it, although not in our border to be able to defend it easily. If no allied market, our second market will
* follow the same logic
* TODO check that it is on same accessIndex
*/
m.HQ.prototype.findMarketLocation = function(gameState, template)
{
var markets = gameState.updatingCollection("ExclusiveAllyMarkets", API3.Filters.byClass("Market"), gameState.getExclusiveAllyEntities()).toEntityArray();
@ -1105,8 +1114,10 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
return [x, z, this.basesMap.map[bestJdx], expectedGain];
};
// Returns the best position to build defensive buildings (fortress and towers)
// Whose primary function is to defend our borders
/**
* Returns the best position to build defensive buildings (fortress and towers)
* Whose primary function is to defend our borders
*/
m.HQ.prototype.findDefensiveLocation = function(gameState, template)
{
// We take the point in our territory which is the nearest to any enemy cc
@ -1273,12 +1284,12 @@ m.HQ.prototype.buildMarket = function(gameState, queues)
return;
gameState.ai.queueManager.changePriority("economicBuilding", 3*this.Config.priorities.economicBuilding);
var plan = new m.ConstructionPlan(gameState, "structures/{civ}_market");
let plan = new m.ConstructionPlan(gameState, "structures/{civ}_market");
plan.onStart = function(gameState) { gameState.ai.queueManager.changePriority("economicBuilding", gameState.ai.Config.priorities.economicBuilding); };
queues.economicBuilding.addPlan(plan);
};
// Build a farmstead
/** Build a farmstead */
m.HQ.prototype.buildFarmstead = function(gameState, queues)
{
// Only build one farmstead for the time being ("DropsiteFood" does not refer to CCs)
@ -1297,7 +1308,7 @@ m.HQ.prototype.buildFarmstead = function(gameState, queues)
queues.economicBuilding.addPlan(new m.ConstructionPlan(gameState, "structures/{civ}_farmstead"));
};
// Build a corral, and train animals there
/** Build a corral, and train animals there */
m.HQ.prototype.manageCorral = function(gameState, queues)
{
if (queues.corral.hasQueuedUnits())

View file

@ -1,8 +1,7 @@
var PETRA = function(m)
{
/*
/**
* Common functions and variables to all queue plans.
* has a "--" suffix because it needs to be loaded before the other queueplan files.
*/
m.QueuePlan = function(gameState, type, metadata)
@ -25,25 +24,25 @@ m.QueuePlan = function(gameState, type, metadata)
return true;
};
// Check the content of this queue
/** Check the content of this queue */
m.QueuePlan.prototype.isInvalid = function(gameState)
{
return false;
};
// if true, the queue manager will begin increasing this plan's account.
/** if true, the queue manager will begin increasing this plan's account. */
m.QueuePlan.prototype.isGo = function(gameState)
{
return true;
};
// can we start this plan immediately?
/** can we start this plan immediately? */
m.QueuePlan.prototype.canStart = function(gameState)
{
return false;
};
// process the plan.
/** process the plan. */
m.QueuePlan.prototype.start = function(gameState)
{
// should call onStart.
@ -51,17 +50,19 @@ m.QueuePlan.prototype.start = function(gameState)
m.QueuePlan.prototype.getCost = function()
{
var costs = new API3.Resources();
let costs = new API3.Resources();
costs.add(this.cost);
if (this.number !== 1)
costs.multiply(this.number);
return costs;
};
// On Event functions.
// Can be used to do some specific stuffs
// Need to be updated to actually do something if you want them to.
// this is called by "Start" if it succeeds.
/**
* On Event functions.
* Can be used to do some specific stuffs
* Need to be updated to actually do something if you want them to.
* this is called by "Start" if it succeeds.
*/
m.QueuePlan.prototype.onStart = function(gameState)
{
};

View file

@ -12,7 +12,7 @@ m.ResearchPlan = function(gameState, type, rush = false)
this.category = "technology";
this.rush = rush;
return true;
};
@ -31,7 +31,7 @@ m.ResearchPlan.prototype.isInvalid = function(gameState)
m.ResearchPlan.prototype.start = function(gameState)
{
var trainers = gameState.findResearchers(this.type).toEntityArray();
let trainers = gameState.findResearchers(this.type).toEntityArray();
// Prefer training buildings with short queues
// (TODO: this should also account for units added to the queue by

View file

@ -11,7 +11,7 @@ m.TrainingPlan = function(gameState, type, metadata, number = 1, maxMerge = 5)
this.category = "unit";
this.cost = new API3.Resources(this.template.cost(), +this.template._template.Cost.Population);
this.number = number;
this.maxMerge = maxMerge;
@ -113,10 +113,10 @@ m.TrainingPlan.prototype.addItem = function(amount = 1)
// Find the promoted types corresponding to this.type
m.TrainingPlan.prototype.promotedTypes = function(gameState)
{
var types = [];
var promotion = this.template.promotion();
var previous;
var template;
let types = [];
let promotion = this.template.promotion();
let previous;
let template;
while (promotion)
{
types.push(promotion);

View file

@ -18,8 +18,8 @@ m.ResearchManager.prototype.checkPhase = function(gameState, queues)
if (queues.majorTech.hasQueuedUnits())
return;
var townPhase = gameState.townPhase();
var cityPhase = gameState.cityPhase();
let townPhase = gameState.townPhase();
let cityPhase = gameState.cityPhase();
if (gameState.canResearch(townPhase,true) && gameState.getPopulation() >= this.Config.Economy.popForTown - 10 &&
gameState.hasResearchers(townPhase, true))
@ -51,8 +51,8 @@ m.ResearchManager.prototype.researchPopulationBonus = function(gameState, queues
if (queues.minorTech.hasQueuedUnits())
return;
var techs = gameState.findAvailableTech();
for (var tech of techs)
let techs = gameState.findAvailableTech();
for (let tech of techs)
{
if (!tech[1]._template.modifications)
continue;
@ -69,8 +69,8 @@ m.ResearchManager.prototype.researchTradeBonus = function(gameState, queues)
if (queues.minorTech.hasQueuedUnits())
return;
var techs = gameState.findAvailableTech();
for (var tech of techs)
let techs = gameState.findAvailableTech();
for (let tech of techs)
{
if (!tech[1]._template.modifications || !tech[1]._template.affects)
continue;
@ -85,11 +85,11 @@ m.ResearchManager.prototype.researchTradeBonus = function(gameState, queues)
}
};
// Techs to be searched for as soon as they are available
/** Techs to be searched for as soon as they are available */
m.ResearchManager.prototype.researchWantedTechs = function(gameState, techs)
{
var available = gameState.currentPhase() === 1 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
var numWorkers = gameState.currentPhase() === 1 ? gameState.getOwnEntitiesByRole("worker", true).length : 0;
let available = gameState.currentPhase() === 1 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
let numWorkers = gameState.currentPhase() === 1 ? gameState.getOwnEntitiesByRole("worker", true).length : 0;
for (let tech of techs)
{
if (!tech[1]._template.modifications)
@ -123,11 +123,11 @@ m.ResearchManager.prototype.researchWantedTechs = function(gameState, techs)
return false;
};
// Techs to be searched for as soon as they are available, but only after phase 2
/** Techs to be searched for as soon as they are available, but only after phase 2 */
m.ResearchManager.prototype.researchPreferredTechs = function(gameState, techs)
{
var available = gameState.currentPhase() === 2 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
var numWorkers = gameState.currentPhase() === 2 ? gameState.getOwnEntitiesByRole("worker", true).length : 0;
let available = gameState.currentPhase() === 2 ? gameState.ai.queueManager.getAvailableResources(gameState) : null;
let numWorkers = gameState.currentPhase() === 2 ? gameState.getOwnEntitiesByRole("worker", true).length : 0;
for (let tech of techs)
{
if (!tech[1]._template.modifications)
@ -164,9 +164,9 @@ m.ResearchManager.prototype.update = function(gameState, queues)
if (queues.minorTech.hasQueuedUnits() || queues.majorTech.hasQueuedUnits())
return;
var techs = gameState.findAvailableTech();
let techs = gameState.findAvailableTech();
var techName = this.researchWantedTechs(gameState, techs);
let techName = this.researchWantedTechs(gameState, techs);
if (techName)
{
queues.minorTech.addPlan(new m.ResearchPlan(gameState, techName));
@ -208,7 +208,7 @@ m.ResearchManager.prototype.update = function(gameState, queues)
if (!techs.length)
return;
// randomly pick one. No worries about pairs in that case.
var p = Math.floor(Math.random()*techs.length);
let p = Math.floor(Math.random()*techs.length);
queues.minorTech.addPlan(new m.ResearchPlan(gameState, techs[p][0]));
};

View file

@ -1,27 +1,27 @@
var PETRA = function(m)
{
/*
Describes a transport plan
Constructor assign units (units is an ID array), a destionation (position).
The naval manager will try to deal with it accordingly.
By this I mean that the naval manager will find how to go from access point 1 to access point 2 (relying on in-game pathfinder for mvt)
And then carry units from there.
Note: only assign it units currently over land, or it won't work.
Also: destination should probably be land, otherwise the units will be lost at sea.
metadata for units:
transport = this.ID
onBoard = ship.id() when affected to a ship but not yet garrisoned
= "onBoard" when garrisoned in a ship
= undefined otherwise
endPos = position of destination
metadata for ships
transporter = this.ID
*/
/**
* Describes a transport plan
* Constructor assign units (units is an ID array), a destination (position).
* The naval manager will try to deal with it accordingly.
*
* By this I mean that the naval manager will find how to go from access point 1 to access point 2
* and then carry units from there.
*
* Note: only assign it units currently over land, or it won't work.
* Also: destination should probably be land, otherwise the units will be lost at sea.
*
* metadata for units:
* transport = this.ID
* onBoard = ship.id() when affected to a ship but not yet garrisoned
* = "onBoard" when garrisoned in a ship
* = undefined otherwise
* endPos = position of destination
*
* metadata for ships
* transporter = this.ID
*/
m.TransportPlan = function(gameState, units, startIndex, endIndex, endPos, ship)
{
@ -89,11 +89,11 @@ m.TransportPlan.prototype.init = function(gameState)
this.boardingRange = 18*18; // TODO compute it from the ship clearance and garrison range
};
// count available slots
/** count available slots */
m.TransportPlan.prototype.countFreeSlots = function()
{
var self = this;
var slots = 0;
let self = this;
let slots = 0;
this.transportShips.forEach(function (ship) { slots += self.countFreeSlotsOnShip(ship); });
return slots;
};
@ -135,7 +135,7 @@ m.TransportPlan.prototype.assignUnitToShip = function(gameState, ent)
m.TransportPlan.prototype.assignShip = function(gameState)
{
var pos;
let pos;
// choose a unit of this plan not yet assigned to a ship
for (let ent of this.units.values())
{
@ -145,8 +145,8 @@ m.TransportPlan.prototype.assignShip = function(gameState)
break;
}
// and choose the nearest available ship from this unit
var distmin = Math.min();
var nearest;
let distmin = Math.min();
let nearest;
gameState.ai.HQ.navalManager.seaTransportShips[this.sea].forEach(function (ship) {
if (ship.getMetadata(PlayerID, "transporter"))
return;
@ -171,7 +171,7 @@ m.TransportPlan.prototype.assignShip = function(gameState)
return true;
};
// add a unit to this plan
/** add a unit to this plan */
m.TransportPlan.prototype.addUnit = function(unit, endPos)
{
unit.setMetadata(PlayerID, "transport", this.ID);
@ -199,8 +199,8 @@ m.TransportPlan.prototype.releaseAll = function()
m.TransportPlan.prototype.cancelTransport = function(gameState)
{
var ent = this.units.toEntityArray()[0];
var base = gameState.ai.HQ.getBaseByID(ent.getMetadata(PlayerID, "base"));
let ent = this.units.toEntityArray()[0];
let base = gameState.ai.HQ.getBaseByID(ent.getMetadata(PlayerID, "base"));
if (!base.anchor || !base.anchor.position())
{
for (let newbase of gameState.ai.HQ.baseManagers)
@ -224,11 +224,11 @@ m.TransportPlan.prototype.cancelTransport = function(gameState)
};
/*
try to move on. There are two states:
- "boarding" means we're trying to board units onto our ships
- "sailing" means we're moving ships and eventually unload units
- then the plan is cleared
/**
* try to move on. There are two states:
* - "boarding" means we're trying to board units onto our ships
* - "sailing" means we're moving ships and eventually unload units
* - then the plan is cleared
*/
m.TransportPlan.prototype.update = function(gameState)
@ -243,9 +243,9 @@ m.TransportPlan.prototype.update = function(gameState)
m.TransportPlan.prototype.onBoarding = function(gameState)
{
var ready = true;
var self = this;
var time = gameState.ai.elapsedTime;
let ready = true;
let self = this;
let time = gameState.ai.elapsedTime;
this.units.forEach(function (ent) {
if (!ent.getMetadata(PlayerID, "onBoard"))
{
@ -342,7 +342,7 @@ m.TransportPlan.prototype.onBoarding = function(gameState)
this.recovered = [];
};
// tell if a unit is garrisoned in one of the ships of this plan, and update its metadata if yes
/** tell if a unit is garrisoned in one of the ships of this plan, and update its metadata if yes */
m.TransportPlan.prototype.isOnBoard = function(ent)
{
for (let ship of this.transportShips.values())
@ -355,7 +355,7 @@ m.TransportPlan.prototype.isOnBoard = function(ent)
return false;
};
// when avoidEnnemy is true, we try to not board/unboard in ennemy territory
/** when avoidEnnemy is true, we try to not board/unboard in ennemy territory */
m.TransportPlan.prototype.getBoardingPos = function(gameState, ship, landIndex, seaIndex, destination, avoidEnnemy)
{
if (!gameState.ai.HQ.navalManager.landingZones[landIndex])
@ -369,11 +369,11 @@ m.TransportPlan.prototype.getBoardingPos = function(gameState, ship, landIndex,
return destination;
}
var startPos = ship.position();
var distmin = Math.min();
var posmin = destination;
var width = gameState.getMap().width;
var cell = gameState.getMap().cellSize;
let startPos = ship.position();
let distmin = Math.min();
let posmin = destination;
let width = gameState.getMap().width;
let cell = gameState.getMap().cellSize;
let alliedDocks = gameState.getAllyStructures().filter(API3.Filters.and(
API3.Filters.byClass("Dock"), API3.Filters.byMetadata(PlayerID, "sea", seaIndex))).toEntityArray();
for (let i of gameState.ai.HQ.navalManager.landingZones[landIndex][seaIndex])
@ -392,8 +392,9 @@ m.TransportPlan.prototype.getBoardingPos = function(gameState, ship, landIndex,
// require a small distance between all ships of the transport plan to avoid path finder problems
// this is also used when the ship is blocked and we want to find a new boarding point
for (let shipId in this.boardingPos)
if (this.boardingPos[shipId] !== undefined && API3.SquareVectorDistance(this.boardingPos[shipId], pos) < this.boardingRange)
dist += 1000000;
if (this.boardingPos[shipId] !== undefined &&
API3.SquareVectorDistance(this.boardingPos[shipId], pos) < this.boardingRange)
dist += 1000000;
// and not too near our allied docks to not disturb naval traffic
for (let dock of alliedDocks)
{
@ -452,7 +453,7 @@ m.TransportPlan.prototype.onSailing = function(gameState)
this.recovered = [];
// Check that the units unloaded on the previous turn have been really unloaded and in the right position
var shipsToMove = {};
let shipsToMove = {};
for (let entId of this.unloaded)
{
let ent = gameState.getEntityById(entId);
@ -529,9 +530,9 @@ m.TransportPlan.prototype.onSailing = function(gameState)
{
if (ship.unitAIState() === "INDIVIDUAL.WALKING")
continue;
var shipId = ship.id();
var dist = API3.SquareVectorDistance(ship.position(), this.boardingPos[shipId]);
var remaining = 0;
let shipId = ship.id();
let dist = API3.SquareVectorDistance(ship.position(), this.boardingPos[shipId]);
let remaining = 0;
for (let entId of ship.garrisoned())
{
let ent = gameState.getEntityById(entId);
@ -546,7 +547,7 @@ m.TransportPlan.prototype.onSailing = function(gameState)
}
}
var recovering = 0;
let recovering = 0;
for (let recov of this.recovered)
if (recov.shipId === shipId)
recovering++;