mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-07-04 05:55:47 -07:00
petra cleanup
This was SVN commit r17677.
This commit is contained in:
parent
0a64bf25cd
commit
dd545bdbf1
8 changed files with 217 additions and 229 deletions
|
|
@ -194,8 +194,8 @@ m.AttackManager.prototype.update = function(gameState, queues, events)
|
|||
if (unexecutedAttacks.Rush === 0)
|
||||
{
|
||||
// we have a barracks and we want to rush, rush.
|
||||
var data = { "targetSize": this.rushSize[this.rushNumber] };
|
||||
var attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, "Rush", data);
|
||||
let data = { "targetSize": this.rushSize[this.rushNumber] };
|
||||
let attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, "Rush", data);
|
||||
if (!attackPlan.failed)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
|
|
@ -210,15 +210,11 @@ m.AttackManager.prototype.update = function(gameState, queues, events)
|
|||
else if (unexecutedAttacks.Attack === 0 && unexecutedAttacks.HugeAttack === 0 &&
|
||||
(this.startedAttacks.Attack.length + this.startedAttacks.HugeAttack.length < Math.min(2, 1 + Math.round(gameState.getPopulationMax()/100))))
|
||||
{
|
||||
if ((barracksNb >= 1 && (gameState.currentPhase() > 1 || gameState.isResearching(gameState.townPhase())))
|
||||
|| !gameState.ai.HQ.baseManagers[1]) // if we have no base ... nothing else to do than attack
|
||||
if ((barracksNb >= 1 && (gameState.currentPhase() > 1 || gameState.isResearching(gameState.townPhase()))) ||
|
||||
!gameState.ai.HQ.baseManagers[1]) // if we have no base ... nothing else to do than attack
|
||||
{
|
||||
if (this.attackNumber < 2 || this.startedAttacks.HugeAttack.length > 0)
|
||||
var type = "Attack";
|
||||
else
|
||||
var type = "HugeAttack";
|
||||
|
||||
var attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, type);
|
||||
let type = (this.attackNumber < 2 || this.startedAttacks.HugeAttack.length > 0) ? "Attack" : "HugeAttack";
|
||||
let attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, type);
|
||||
if (attackPlan.failed)
|
||||
this.attackPlansEncounteredWater = true; // hack
|
||||
else
|
||||
|
|
@ -235,7 +231,7 @@ m.AttackManager.prototype.update = function(gameState, queues, events)
|
|||
|
||||
if (unexecutedAttacks.Raid === 0 && gameState.ai.HQ.defenseManager.targetList.length)
|
||||
{
|
||||
var target = undefined;
|
||||
let target;
|
||||
for (let targetId of gameState.ai.HQ.defenseManager.targetList)
|
||||
{
|
||||
target = gameState.getEntityById(targetId);
|
||||
|
|
@ -245,8 +241,8 @@ m.AttackManager.prototype.update = function(gameState, queues, events)
|
|||
if (target)
|
||||
{
|
||||
// prepare a raid against this target
|
||||
var data = { "target": target };
|
||||
var attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, "Raid", data);
|
||||
let data = { "target": target };
|
||||
let attackPlan = new m.AttackPlan(gameState, this.Config, this.totalNumber, "Raid", data);
|
||||
if (!attackPlan.failed)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
|
|
@ -293,23 +289,23 @@ m.AttackManager.prototype.unpausePlan = function(planName)
|
|||
|
||||
m.AttackManager.prototype.pauseAllPlans = function()
|
||||
{
|
||||
for (var attackType in this.upcomingAttacks)
|
||||
for (var attack of this.upcomingAttacks[attackType])
|
||||
for (let attackType in this.upcomingAttacks)
|
||||
for (let attack of this.upcomingAttacks[attackType])
|
||||
attack.setPaused(true);
|
||||
|
||||
for (var attackType in this.startedAttacks)
|
||||
for (var attack of this.startedAttacks[attackType])
|
||||
for (let attackType in this.startedAttacks)
|
||||
for (let attack of this.startedAttacks[attackType])
|
||||
attack.setPaused(true);
|
||||
};
|
||||
|
||||
m.AttackManager.prototype.unpauseAllPlans = function()
|
||||
{
|
||||
for (var attackType in this.upcomingAttacks)
|
||||
for (var attack of this.upcomingAttacks[attackType])
|
||||
for (let attackType in this.upcomingAttacks)
|
||||
for (let attack of this.upcomingAttacks[attackType])
|
||||
attack.setPaused(false);
|
||||
|
||||
for (var attackType in this.startedAttacks)
|
||||
for (var attack of this.startedAttacks[attackType])
|
||||
for (let attackType in this.startedAttacks)
|
||||
for (let attack of this.startedAttacks[attackType])
|
||||
attack.setPaused(false);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -105,9 +105,9 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
|||
if (type === "Rush")
|
||||
{
|
||||
priority = 250;
|
||||
this.unitStat["Infantry"] = { "priority": 1, "minSize": 10, "targetSize": 20, "batchSize": 2, "classes": ["Infantry"],
|
||||
this.unitStat.Infantry = { "priority": 1, "minSize": 10, "targetSize": 20, "batchSize": 2, "classes": ["Infantry"],
|
||||
"interests": [ ["strength",1], ["cost",1], ["costsResource", 0.5, "stone"], ["costsResource", 0.6, "metal"] ] };
|
||||
this.unitStat["Cavalry"] = { "priority": 1, "minSize": 2, "targetSize": 4, "batchSize": 2, "classes": ["Cavalry", "CitizenSoldier"],
|
||||
this.unitStat.Cavalry = { "priority": 1, "minSize": 2, "targetSize": 4, "batchSize": 2, "classes": ["Cavalry", "CitizenSoldier"],
|
||||
"interests": [ ["strength",1], ["cost",1] ] };
|
||||
if (data && data.targetSize)
|
||||
this.unitStat["Infantry"]["targetSize"] = data.targetSize;
|
||||
|
|
@ -116,7 +116,7 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
|||
else if (type === "Raid")
|
||||
{
|
||||
priority = 150;
|
||||
this.unitStat["Cavalry"] = { "priority": 1, "minSize": 3, "targetSize": 4, "batchSize": 2, "classes": ["Cavalry", "CitizenSoldier"],
|
||||
this.unitStat.Cavalry = { "priority": 1, "minSize": 3, "targetSize": 4, "batchSize": 2, "classes": ["Cavalry", "CitizenSoldier"],
|
||||
"interests": [ ["strength",1], ["cost",1] ] };
|
||||
this.neededShips = 1;
|
||||
}
|
||||
|
|
@ -124,34 +124,34 @@ 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": 15, "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": 15, "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": 5, "targetSize": 25, "batchSize": 5, "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": 5, "targetSize": 20, "batchSize": 5, "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.MeleeCavalry = { "priority": 0.7, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry","Melee", "CitizenSoldier"],
|
||||
"interests": [ ["strength",2], ["cost",1] ] };
|
||||
this.unitStat["RangedCavalry"] = { "priority": 0.7, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry","Ranged", "CitizenSoldier"],
|
||||
this.unitStat.RangedCavalry = { "priority": 0.7, "minSize": 3, "targetSize": 15, "batchSize": 3, "classes": ["Cavalry","Ranged", "CitizenSoldier"],
|
||||
"interests": [ ["strength",2], ["cost",1] ] };
|
||||
this.unitStat["ChampMeleeInfantry"] = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "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["ChampMeleeCavalry"] = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "classes": ["Cavalry","Melee", "Champion"],
|
||||
this.unitStat.ChampMeleeCavalry = { "priority": 1, "minSize": 3, "targetSize": 18, "batchSize": 3, "classes": ["Cavalry","Melee", "Champion"],
|
||||
"interests": [ ["strength",2], ["cost",1] ] };
|
||||
this.unitStat["Hero"] = { "priority": 1, "minSize": 0, "targetSize": 1, "batchSize": 1, "classes": ["Hero"],
|
||||
this.unitStat.Hero = { "priority": 1, "minSize": 0, "targetSize": 1, "batchSize": 1, "classes": ["Hero"],
|
||||
"interests": [ ["strength",2], ["cost",1] ] };
|
||||
this.neededShips = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
priority = 70;
|
||||
this.unitStat["RangedInfantry"] = { "priority": 1, "minSize": 6, "targetSize": 16, "batchSize": 3, "classes": ["Infantry","Ranged"],
|
||||
this.unitStat.RangedInfantry = { "priority": 1, "minSize": 6, "targetSize": 16, "batchSize": 3, "classes": ["Infantry","Ranged"],
|
||||
"interests": [ ["canGather", 1], ["strength",1.6], ["cost",1.5], ["costsResource", 0.3, "stone"], ["costsResource", 0.3, "metal"] ] };
|
||||
this.unitStat["MeleeInfantry"] = { "priority": 1, "minSize": 6, "targetSize": 16, "batchSize": 3, "classes": ["Infantry","Melee"],
|
||||
this.unitStat.MeleeInfantry = { "priority": 1, "minSize": 6, "targetSize": 16, "batchSize": 3, "classes": ["Infantry","Melee"],
|
||||
"interests": [ ["canGather", 1], ["strength",1.6], ["cost",1.5], ["costsResource", 0.3, "stone"], ["costsResource", 0.3, "metal"] ] };
|
||||
this.unitStat["Cavalry"] = { "priority": 1, "minSize": 2, "targetSize": 6, "batchSize": 2, "classes": ["Cavalry", "CitizenSoldier"],
|
||||
this.unitStat.Cavalry = { "priority": 1, "minSize": 2, "targetSize": 6, "batchSize": 2, "classes": ["Cavalry", "CitizenSoldier"],
|
||||
"interests": [ ["strength",1], ["cost",1] ] };
|
||||
this.neededShips = 3;
|
||||
}
|
||||
|
|
@ -171,16 +171,16 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
|||
}
|
||||
for (let cat in this.unitStat)
|
||||
{
|
||||
this.unitStat[cat]["targetSize"] = Math.round(variation * this.unitStat[cat]["targetSize"]);
|
||||
this.unitStat[cat]["minSize"] = Math.min(this.unitStat[cat]["minSize"], this.unitStat[cat]["targetSize"]);
|
||||
this.unitStat[cat].targetSize = Math.round(variation * this.unitStat[cat].targetSize);
|
||||
this.unitStat[cat].minSize = Math.min(this.unitStat[cat].minSize, this.unitStat[cat].targetSize);
|
||||
}
|
||||
|
||||
// change the sizes according to max population
|
||||
this.neededShips = Math.ceil(this.Config.popScaling * this.neededShips);
|
||||
for (let cat in this.unitStat)
|
||||
{
|
||||
this.unitStat[cat]["targetSize"] = Math.round(this.Config.popScaling * this.unitStat[cat]["targetSize"]);
|
||||
this.unitStat[cat]["minSize"] = Math.floor(this.Config.popScaling * this.unitStat[cat]["minSize"]);
|
||||
this.unitStat[cat].targetSize = Math.round(this.Config.popScaling * this.unitStat[cat].targetSize);
|
||||
this.unitStat[cat].minSize = Math.floor(this.Config.popScaling * this.unitStat[cat].minSize);
|
||||
}
|
||||
|
||||
// TODO: there should probably be one queue per type of training building
|
||||
|
|
@ -219,10 +219,10 @@ m.AttackPlan.prototype.init = function(gameState)
|
|||
for (let cat in this.unitStat)
|
||||
{
|
||||
let Unit = this.unitStat[cat];
|
||||
this.unit[cat] = this.unitCollection.filter(API3.Filters.byClassesAnd(Unit["classes"]));
|
||||
this.unit[cat] = this.unitCollection.filter(API3.Filters.byClassesAnd(Unit.classes));
|
||||
this.unit[cat].registerUpdates();
|
||||
if (this.canBuildUnits)
|
||||
this.buildOrder.push([0, Unit["classes"], this.unit[cat], Unit, cat]);
|
||||
this.buildOrder.push([0, Unit.classes, this.unit[cat], Unit, cat]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -259,11 +259,9 @@ m.AttackPlan.prototype.canStart = function()
|
|||
return true;
|
||||
|
||||
for (let unitCat in this.unitStat)
|
||||
{
|
||||
let Unit = this.unitStat[unitCat];
|
||||
if (this.unit[unitCat].length < Unit["minSize"])
|
||||
if (this.unit[unitCat].length < this.unitStat[unitCat].minSize)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -280,9 +278,9 @@ m.AttackPlan.prototype.mustStart = function()
|
|||
for (let unitCat in this.unitStat)
|
||||
{
|
||||
let Unit = this.unitStat[unitCat];
|
||||
if (this.unit[unitCat].length < Unit["targetSize"])
|
||||
if (this.unit[unitCat].length < Unit.targetSize)
|
||||
MaxReachedEverywhere = false;
|
||||
if (this.unit[unitCat].length < Unit["minSize"])
|
||||
if (this.unit[unitCat].length < Unit.minSize)
|
||||
{
|
||||
MinReachedEverywhere = false;
|
||||
break;
|
||||
|
|
@ -304,8 +302,8 @@ m.AttackPlan.prototype.forceStart = function()
|
|||
for (let unitCat in this.unitStat)
|
||||
{
|
||||
let Unit = this.unitStat[unitCat];
|
||||
Unit["targetSize"] = 0;
|
||||
Unit["minSize"] = 0;
|
||||
Unit.targetSize = 0;
|
||||
Unit.minSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -317,9 +315,9 @@ m.AttackPlan.prototype.addBuildOrder = function(gameState, name, unitStats, rese
|
|||
// no minsize as we don't want the plan to fail at the last minute though.
|
||||
this.unitStat[name] = unitStats;
|
||||
let Unit = this.unitStat[name];
|
||||
this.unit[name] = this.unitCollection.filter(API3.Filters.byClassesAnd(Unit["classes"]));
|
||||
this.unit[name] = this.unitCollection.filter(API3.Filters.byClassesAnd(Unit.classes));
|
||||
this.unit[name].registerUpdates();
|
||||
this.buildOrder.push([0, Unit["classes"], this.unit[name], Unit, name]);
|
||||
this.buildOrder.push([0, Unit.classes, this.unit[name], Unit, name]);
|
||||
if (resetQueue)
|
||||
{
|
||||
this.queue.empty();
|
||||
|
|
@ -331,18 +329,18 @@ m.AttackPlan.prototype.addBuildOrder = function(gameState, name, unitStats, rese
|
|||
|
||||
m.AttackPlan.prototype.addSiegeUnits = function(gameState)
|
||||
{
|
||||
if (this.unitStat["Siege"] || this.state !== "unexecuted")
|
||||
if (this.unitStat.Siege || this.state !== "unexecuted")
|
||||
return false;
|
||||
// no minsize as we don't want the plan to fail at the last minute though.
|
||||
var stat = { "priority": 1., "minSize": 0, "targetSize": 4, "batchSize": 2, "classes": ["Siege"],
|
||||
var stat = { "priority": 1, "minSize": 0, "targetSize": 4, "batchSize": 2, "classes": ["Siege"],
|
||||
"interests": [ ["siegeStrength", 3], ["cost",1] ] };
|
||||
if (gameState.civ() === "maur")
|
||||
stat["classes"] = ["Elephant", "Champion"];
|
||||
stat.classes = ["Elephant", "Champion"];
|
||||
if (this.Config.difficulty < 2)
|
||||
stat["targetSize"] = 1;
|
||||
stat.targetSize = 1;
|
||||
else if (this.Config.difficulty < 3)
|
||||
stat["targetSize"] = 2;
|
||||
stat["targetSize"] = Math.round(this.Config.popScaling * stat["targetSize"]);
|
||||
stat.targetSize = 2;
|
||||
stat.targetSize = Math.round(this.Config.popScaling * stat.targetSize);
|
||||
this.addBuildOrder(gameState, "Siege", stat, true);
|
||||
return true;
|
||||
};
|
||||
|
|
@ -372,7 +370,7 @@ m.AttackPlan.prototype.updatePreparation = function(gameState)
|
|||
}
|
||||
}
|
||||
|
||||
if (this.Config.debug > 3 && gameState.ai.playedTurn % 50 == 0)
|
||||
if (this.Config.debug > 3 && gameState.ai.playedTurn % 50 === 0)
|
||||
this.debugAttack();
|
||||
|
||||
// if we need a transport, wait for some transport ships
|
||||
|
|
@ -400,14 +398,14 @@ m.AttackPlan.prototype.updatePreparation = function(gameState)
|
|||
if (this.Config.debug > 1)
|
||||
{
|
||||
var am = gameState.ai.HQ.attackManager;
|
||||
API3.warn(" attacks upcoming: raid " + am.upcomingAttacks["Raid"].length
|
||||
+ " rush " + am.upcomingAttacks["Rush"].length
|
||||
+ " attack " + am.upcomingAttacks["Attack"].length
|
||||
+ " huge " + am.upcomingAttacks["HugeAttack"].length);
|
||||
API3.warn(" attacks started: raid " + am.startedAttacks["Raid"].length
|
||||
+ " rush " + am.startedAttacks["Rush"].length
|
||||
+ " attack " + am.startedAttacks["Attack"].length
|
||||
+ " huge " + am.startedAttacks["HugeAttack"].length);
|
||||
API3.warn(" attacks upcoming: raid " + am.upcomingAttacks.Raid.length +
|
||||
" rush " + am.upcomingAttacks.Rush.length +
|
||||
" attack " + am.upcomingAttacks.Attack.length +
|
||||
" huge " + am.upcomingAttacks.HugeAttack.length);
|
||||
API3.warn(" attacks started: raid " + am.startedAttacks.Raid.length +
|
||||
" rush " + am.startedAttacks.Rush.length +
|
||||
" attack " + am.startedAttacks.Attack.length +
|
||||
" huge " + am.startedAttacks.HugeAttack.length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -425,7 +423,7 @@ m.AttackPlan.prototype.updatePreparation = function(gameState)
|
|||
if (this.canBuildUnits)
|
||||
{
|
||||
// We still have time left to recruit units and do stuffs.
|
||||
if (!this.unitStat["Siege"])
|
||||
if (!this.unitStat.Siege)
|
||||
{
|
||||
var numSiegeBuilder = 0;
|
||||
if (gameState.civ() !== "mace" && gameState.civ() !== "maur")
|
||||
|
|
@ -510,16 +508,16 @@ m.AttackPlan.prototype.trainMoreUnits = function(gameState)
|
|||
this.buildOrder[i][0] = this.buildOrder[i][2].length + aQueued;
|
||||
}
|
||||
this.buildOrder.sort(function (a,b) {
|
||||
let va = a[0]/a[3]["targetSize"] - a[3]["priority"];
|
||||
if (a[0] >= a[3]["targetSize"])
|
||||
let va = a[0]/a[3].targetSize - a[3].priority;
|
||||
if (a[0] >= a[3].targetSize)
|
||||
va += 1000;
|
||||
let vb = b[0]/b[3]["targetSize"] - b[3]["priority"];
|
||||
if (b[0] >= b[3]["targetSize"])
|
||||
let vb = b[0]/b[3].targetSize - b[3].priority;
|
||||
if (b[0] >= b[3].targetSize)
|
||||
vb += 1000;
|
||||
return va - vb;
|
||||
});
|
||||
|
||||
if (this.Config.debug > 1 && gameState.ai.playedTurn%50 == 0)
|
||||
if (this.Config.debug > 1 && gameState.ai.playedTurn%50 === 0)
|
||||
{
|
||||
API3.warn("====================================");
|
||||
API3.warn("======== build order for plan " + this.name);
|
||||
|
|
@ -530,51 +528,51 @@ m.AttackPlan.prototype.trainMoreUnits = function(gameState)
|
|||
let queue1 = this.queue.countQueuedUnitsWithMetadata("special", specialData);
|
||||
let queue2 = this.queueChamp.countQueuedUnitsWithMetadata("special", specialData);
|
||||
let queue3 = this.queueSiege.countQueuedUnitsWithMetadata("special", specialData);
|
||||
API3.warn(" >>> " + order[4] + " done " + order[2].length + " training " + inTraining
|
||||
+ " queue " + queue1 + " champ " + queue2 + " siege " + queue3 + " >> need " + order[3].targetSize);
|
||||
API3.warn(" >>> " + order[4] + " done " + order[2].length + " training " + inTraining +
|
||||
" queue " + queue1 + " champ " + queue2 + " siege " + queue3 + " >> need " + order[3].targetSize);
|
||||
}
|
||||
API3.warn("====================================");
|
||||
}
|
||||
|
||||
if (this.buildOrder[0][0] < this.buildOrder[0][3]["targetSize"])
|
||||
let firstOrder = this.buildOrder[0];
|
||||
if (firstOrder[0] < firstOrder[3].targetSize)
|
||||
{
|
||||
// find the actual queue we want
|
||||
var queue = this.queue;
|
||||
if (this.buildOrder[0][3]["classes"].indexOf("Siege") !== -1 ||
|
||||
(gameState.civ() == "maur" && this.buildOrder[0][3]["classes"].indexOf("Elephant") !== -1 && this.buildOrder[0][3]["classes"].indexOf("Champion")))
|
||||
let queue = this.queue;
|
||||
if (firstOrder[3].classes.indexOf("Siege") !== -1 ||
|
||||
(gameState.civ() == "maur" && firstOrder[3].classes.indexOf("Elephant") !== -1 && firstOrder[3].classes.indexOf("Champion")))
|
||||
queue = this.queueSiege;
|
||||
else if (this.buildOrder[0][3]["classes"].indexOf("Hero") !== -1)
|
||||
else if (firstOrder[3].classes.indexOf("Hero") !== -1)
|
||||
queue = this.queueSiege;
|
||||
else if (this.buildOrder[0][3]["classes"].indexOf("Champion") !== -1)
|
||||
else if (firstOrder[3].classes.indexOf("Champion") !== -1)
|
||||
queue = this.queueChamp;
|
||||
|
||||
if (queue.length() <= 5)
|
||||
{
|
||||
var template = gameState.ai.HQ.findBestTrainableUnit(gameState, this.buildOrder[0][1], this.buildOrder[0][3]["interests"]);
|
||||
let template = gameState.ai.HQ.findBestTrainableUnit(gameState, firstOrder[1], firstOrder[3].interests);
|
||||
// HACK (TODO replace) : if we have no trainable template... Then we'll simply remove the buildOrder,
|
||||
// effectively removing the unit from the plan.
|
||||
if (template === undefined)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("attack no template found " + this.buildOrder[0][1]);
|
||||
delete this.unitStat[this.buildOrder[0][4]]; // deleting the associated unitstat.
|
||||
API3.warn("attack no template found " + firstOrder[1]);
|
||||
delete this.unitStat[firstOrder[4]]; // deleting the associated unitstat.
|
||||
this.buildOrder.splice(0,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.Config.debug > 2)
|
||||
API3.warn("attack template " + template + " added for plan " + this.name);
|
||||
var max = this.buildOrder[0][3]["batchSize"];
|
||||
var specialData = "Plan_" + this.name + "_" + this.buildOrder[0][4];
|
||||
if (gameState.getTemplate(template).hasClass("CitizenSoldier"))
|
||||
var trainingPlan = new m.TrainingPlan(gameState, template, { "role": "worker", "plan": this.name, "special": specialData, "base": 0 }, max, max);
|
||||
else
|
||||
var trainingPlan = new m.TrainingPlan(gameState, template, { "role": "attack", "plan": this.name, "special": specialData, "base": 0 }, max, max);
|
||||
let max = firstOrder[3].batchSize;
|
||||
let specialData = "Plan_" + this.name + "_" + firstOrder[4];
|
||||
let data = { "plan": this.name, "special": specialData, "base": 0 };
|
||||
data.role = gameState.getTemplate(template).hasClass("CitizenSoldier") ? "worker" : "attack";
|
||||
let trainingPlan = new m.TrainingPlan(gameState, template, data, max, max);
|
||||
if (trainingPlan.template)
|
||||
queue.addPlan(trainingPlan);
|
||||
else if (this.Config.debug > 1)
|
||||
API3.warn("training plan canceled because no template for " + template + " build1 " + uneval(this.buildOrder[0][1])
|
||||
+ " build3 " + uneval(this.buildOrder[0][3]["interests"]));
|
||||
API3.warn("training plan canceled because no template for " + template + " build1 " + uneval(firstOrder[1]) +
|
||||
" build3 " + uneval(firstOrder[3].interests));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1068,9 +1066,8 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
{
|
||||
if (IDs.indexOf(evt.target) == -1)
|
||||
continue;
|
||||
var attacker = gameState.getEntityById(evt.attacker);
|
||||
var ourUnit = gameState.getEntityById(evt.target);
|
||||
if (!attacker || !ourUnit)
|
||||
let attacker = gameState.getEntityById(evt.attacker);
|
||||
if (!attacker || !gameState.getEntityById(evt.target))
|
||||
continue;
|
||||
for (let ent of this.unitCollection.values())
|
||||
{
|
||||
|
|
@ -1096,11 +1093,9 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
var attackedUnitNB = 0;
|
||||
for (let evt of events.Attacked)
|
||||
{
|
||||
if (IDs.indexOf(evt.target) == -1)
|
||||
if (IDs.indexOf(evt.target) === -1)
|
||||
continue;
|
||||
var attacker = gameState.getEntityById(evt.attacker);
|
||||
var ourUnit = gameState.getEntityById(evt.target);
|
||||
|
||||
let attacker = gameState.getEntityById(evt.attacker);
|
||||
if (attacker && (attacker.owner() !== 0 || this.targetPlayer === 0))
|
||||
{
|
||||
attackedNB++;
|
||||
|
|
@ -1112,7 +1107,7 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
var maybe = true;
|
||||
if (attackedUnitNB == 0)
|
||||
{
|
||||
var siegeNB = 0;
|
||||
let siegeNB = 0;
|
||||
for (let ent of this.unitCollection.values())
|
||||
if (this.isSiegeUnit(gameState, ent))
|
||||
siegeNB++;
|
||||
|
|
@ -1341,11 +1336,11 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
{ // if units are attacked, abandon their target (if it was a structure or a support) and retaliate
|
||||
// also if our unit is attacking a range unit and the attacker is a melee unit, retaliate
|
||||
var orderData = ourUnit.unitAIOrderData();
|
||||
if (orderData && orderData.length && orderData[0]["target"])
|
||||
if (orderData && orderData.length && orderData[0].target)
|
||||
{
|
||||
if (orderData[0]["target"] === attacker.id())
|
||||
if (orderData[0].target === attacker.id())
|
||||
continue;
|
||||
let target = gameState.getEntityById(orderData[0]["target"]);
|
||||
let target = gameState.getEntityById(orderData[0].target);
|
||||
if (target && !target.hasClass("Structure") && !target.hasClass("Support"))
|
||||
{
|
||||
if (!target.hasClass("Ranged") || !attacker.hasClass("Melee"))
|
||||
|
|
@ -1368,9 +1363,9 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
if (ent.hasClass("Ship")) // TODO What to do with ships
|
||||
continue;
|
||||
let orderData = ent.unitAIOrderData();
|
||||
if (!orderData || !orderData.length || !orderData[0]["target"])
|
||||
if (!orderData || !orderData.length || !orderData[0].target)
|
||||
continue;
|
||||
let targetId = orderData[0]["target"];
|
||||
let targetId = orderData[0].target;
|
||||
let target = gameState.getEntityById(targetId);
|
||||
if (!target || target.hasClass("Structure"))
|
||||
continue;
|
||||
|
|
@ -1419,10 +1414,7 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
this.unitCollUpdateArray = this.unitCollection.toIdArray();
|
||||
|
||||
// Let's check a few units each time we update (currently 10) except when attack starts
|
||||
if (this.unitCollUpdateArray.length < 15 || this.startingAttack)
|
||||
var lgth = this.unitCollUpdateArray.length;
|
||||
else
|
||||
var lgth = 10;
|
||||
var lgth = (this.unitCollUpdateArray.length < 15 || this.startingAttack) ? this.unitCollUpdateArray.length : 10;
|
||||
for (var check = 0; check < lgth; check++)
|
||||
{
|
||||
var ent = gameState.getEntityById(this.unitCollUpdateArray[check]);
|
||||
|
|
@ -1431,8 +1423,8 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
|
||||
let targetId = undefined;
|
||||
let orderData = ent.unitAIOrderData();
|
||||
if (orderData && orderData.length && orderData[0]["target"])
|
||||
targetId = orderData[0]["target"];
|
||||
if (orderData && orderData.length && orderData[0].target)
|
||||
targetId = orderData[0].target;
|
||||
|
||||
// update the order if needed
|
||||
var needsUpdate = false;
|
||||
|
|
@ -1569,14 +1561,14 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
if (mUnit.length !== 0)
|
||||
{
|
||||
mUnit.sort(function (unitA,unitB) {
|
||||
var vala = unitA.hasClass("Support") ? 50 : 0;
|
||||
let vala = unitA.hasClass("Support") ? 50 : 0;
|
||||
if (ent.countersClasses(unitA.classes()))
|
||||
vala += 100;
|
||||
var valb = unitB.hasClass("Support") ? 50 : 0;
|
||||
let valb = unitB.hasClass("Support") ? 50 : 0;
|
||||
if (ent.countersClasses(unitB.classes()))
|
||||
valb += 100;
|
||||
var distA = unitA.getMetadata(PlayerID, "distance");
|
||||
var distB = unitB.getMetadata(PlayerID, "distance");
|
||||
let distA = unitA.getMetadata(PlayerID, "distance");
|
||||
let distB = unitB.getMetadata(PlayerID, "distance");
|
||||
if( distA && distB)
|
||||
{
|
||||
vala -= distA;
|
||||
|
|
@ -1620,12 +1612,12 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
if (mStruct.length !== 0)
|
||||
{
|
||||
mStruct.sort(function (structa,structb) {
|
||||
var vala = structa.costSum();
|
||||
let vala = structa.costSum();
|
||||
if (structa.hasClass("Gates") && ent.canAttackClass("StoneWall"))
|
||||
vala += 10000;
|
||||
else if (structa.hasClass("ConquestCritical"))
|
||||
vala += 100;
|
||||
var valb = structb.costSum();
|
||||
let valb = structb.costSum();
|
||||
if (structb.hasClass("Gates") && ent.canAttackClass("StoneWall"))
|
||||
valb += 10000;
|
||||
else if (structb.hasClass("ConquestCritical"))
|
||||
|
|
@ -1643,19 +1635,19 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
|||
}
|
||||
else if (needsUpdate) // really nothing let's try to help our nearest unit
|
||||
{
|
||||
var distmin = Math.min();
|
||||
var attackerId = undefined;
|
||||
let distmin = Math.min();
|
||||
let attackerId;
|
||||
this.unitCollection.forEach( function (unit) {
|
||||
if (!unit.position())
|
||||
return;
|
||||
if (unit.unitAIState().split(".")[1] !== "COMBAT" || !unit.unitAIOrderData().length
|
||||
|| !unit.unitAIOrderData()[0]["target"])
|
||||
if (unit.unitAIState().split(".")[1] !== "COMBAT" || !unit.unitAIOrderData().length ||
|
||||
!unit.unitAIOrderData()[0].target)
|
||||
return;
|
||||
var dist = API3.SquareVectorDistance(unit.position(), ent.position());
|
||||
let dist = API3.SquareVectorDistance(unit.position(), ent.position());
|
||||
if (dist > distmin)
|
||||
return;
|
||||
distmin = dist;
|
||||
attackerId = unit.unitAIOrderData()[0]["target"];
|
||||
attackerId = unit.unitAIOrderData()[0].target;
|
||||
|
||||
});
|
||||
if (attackerId)
|
||||
|
|
@ -1795,7 +1787,7 @@ m.AttackPlan.prototype.debugAttack = function()
|
|||
for (var unitCat in this.unitStat)
|
||||
{
|
||||
var Unit = this.unitStat[unitCat];
|
||||
API3.warn(unitCat + " num=" + this.unit[unitCat].length + " min=" + Unit["minSize"] + " need=" + Unit["targetSize"]);
|
||||
API3.warn(unitCat + " num=" + this.unit[unitCat].length + " min=" + Unit.minSize + " need=" + Unit.targetSize);
|
||||
}
|
||||
API3.warn("------------------------------");
|
||||
};
|
||||
|
|
@ -1822,8 +1814,8 @@ m.AttackPlan.prototype.CheckCapture = function(gameState, ent)
|
|||
if (!state || !state.split(".")[1] || state.split(".")[1] !== "COMBAT")
|
||||
return true;
|
||||
let orderData = ent.unitAIOrderData();
|
||||
if (!orderData || !orderData.length || !orderData[0].target
|
||||
|| !orderData[0].attackType || orderData[0].attackType !== "Capture")
|
||||
if (!orderData || !orderData.length || !orderData[0].target ||
|
||||
!orderData[0].attackType || orderData[0].attackType !== "Capture")
|
||||
return true;
|
||||
|
||||
let targetId = orderData[0].target;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ m.BaseManager.prototype.init = function(gameState, state)
|
|||
this.dropsites = {};
|
||||
this.dropsiteSupplies = {};
|
||||
this.gatherers = {};
|
||||
for (var type of this.Config.resources)
|
||||
for (let type of this.Config.resources)
|
||||
{
|
||||
this.dropsiteSupplies[type] = {"nearby": [], "medium": [], "faraway": []};
|
||||
this.gatherers[type] = {"nextCheck": 0, "used": 0, "lost": 0};
|
||||
|
|
@ -85,7 +85,7 @@ m.BaseManager.prototype.setAnchor = function(gameState, anchorEntity)
|
|||
this.buildings.updateEnt(this.anchor);
|
||||
this.accessIndex = gameState.ai.accessibility.getAccessValue(this.anchor.position());
|
||||
// in case some of our other bases were destroyed, reaffect these destroyed bases to this base
|
||||
for (var base of gameState.ai.HQ.baseManagers)
|
||||
for (let base of gameState.ai.HQ.baseManagers)
|
||||
{
|
||||
if (base.anchor || base.newbaseID)
|
||||
continue;
|
||||
|
|
@ -100,12 +100,12 @@ m.BaseManager.prototype.checkEvents = function (gameState, events, queues)
|
|||
{
|
||||
// let's check we haven't lost an important building here.
|
||||
if (evt && !evt.SuccessfulFoundation && evt.entityObj && evt.metadata && evt.metadata[PlayerID] &&
|
||||
evt.metadata[PlayerID]["base"] && evt.metadata[PlayerID]["base"] == this.ID)
|
||||
evt.metadata[PlayerID].base && evt.metadata[PlayerID].base == this.ID)
|
||||
{
|
||||
let ent = evt.entityObj;
|
||||
if (ent.resourceDropsiteTypes() && !ent.hasClass("Elephant"))
|
||||
this.removeDropsite(gameState, ent);
|
||||
if (evt.metadata[PlayerID]["baseAnchor"] && evt.metadata[PlayerID]["baseAnchor"] === true)
|
||||
if (evt.metadata[PlayerID].baseAnchor && evt.metadata[PlayerID].baseAnchor === true)
|
||||
this.anchorLost(gameState, ent);
|
||||
}
|
||||
}
|
||||
|
|
@ -202,12 +202,12 @@ m.BaseManager.prototype.assignResourceToDropsite = function (gameState, dropsite
|
|||
for (var type of dropsite.resourceDropsiteTypes())
|
||||
{
|
||||
var resources = gameState.getResourceSupplies(type);
|
||||
if (resources.length == 0)
|
||||
if (!resources.length)
|
||||
continue;
|
||||
|
||||
var nearby = this.dropsiteSupplies[type]["nearby"];
|
||||
var medium = this.dropsiteSupplies[type]["medium"];
|
||||
var faraway = this.dropsiteSupplies[type]["faraway"];
|
||||
var nearby = this.dropsiteSupplies[type].nearby;
|
||||
var medium = this.dropsiteSupplies[type].medium;
|
||||
var faraway = this.dropsiteSupplies[type].faraway;
|
||||
|
||||
resources.forEach(function(supply)
|
||||
{
|
||||
|
|
@ -217,7 +217,7 @@ m.BaseManager.prototype.assignResourceToDropsite = function (gameState, dropsite
|
|||
return;
|
||||
if (supply.hasClass("Field")) // fields are treated separately
|
||||
return;
|
||||
if (supply.resourceSupplyType()["generic"] === "treasure") // treasures are treated separately
|
||||
if (supply.resourceSupplyType().generic === "treasure") // treasures are treated separately
|
||||
return;
|
||||
// quick accessibility check
|
||||
let access = supply.getMetadata(PlayerID, "access");
|
||||
|
|
@ -268,7 +268,7 @@ m.BaseManager.prototype.removeDropsite = function (gameState, ent)
|
|||
return;
|
||||
|
||||
var removeSupply = function(entId, supply){
|
||||
for (var i = 0; i < supply.length; ++i)
|
||||
for (let i = 0; i < supply.length; ++i)
|
||||
{
|
||||
// exhausted resource, remove it from this list
|
||||
if (!supply[i].ent || !gameState.getEntityById(supply[i].id))
|
||||
|
|
@ -279,11 +279,11 @@ m.BaseManager.prototype.removeDropsite = function (gameState, ent)
|
|||
}
|
||||
};
|
||||
|
||||
for (var type in this.dropsiteSupplies)
|
||||
for (let type in this.dropsiteSupplies)
|
||||
{
|
||||
removeSupply(ent.id(), this.dropsiteSupplies[type]["nearby"]);
|
||||
removeSupply(ent.id(), this.dropsiteSupplies[type]["medium"]);
|
||||
removeSupply(ent.id(), this.dropsiteSupplies[type]["faraway"]);
|
||||
removeSupply(ent.id(), this.dropsiteSupplies[type].nearby);
|
||||
removeSupply(ent.id(), this.dropsiteSupplies[type].medium);
|
||||
removeSupply(ent.id(), this.dropsiteSupplies[type].faraway);
|
||||
}
|
||||
|
||||
this.dropsites[ent.id()] = undefined;
|
||||
|
|
@ -558,7 +558,7 @@ m.BaseManager.prototype.setWorkersIdleByPriority = function(gameState)
|
|||
var mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState);
|
||||
var sumWanted = 0;
|
||||
var sumCurrent = 0;
|
||||
for (var need of mostNeeded)
|
||||
for (let need of mostNeeded)
|
||||
{
|
||||
sumWanted += need.wanted;
|
||||
sumCurrent += need.current;
|
||||
|
|
@ -611,7 +611,7 @@ m.BaseManager.prototype.reassignIdleWorkers = function(gameState, idleWorkers)
|
|||
// Search for idle workers, and tell them to gather resources based on demand
|
||||
if (!idleWorkers)
|
||||
{
|
||||
var filter = API3.Filters.byMetadata(PlayerID, "subrole", "idle");
|
||||
let filter = API3.Filters.byMetadata(PlayerID, "subrole", "idle");
|
||||
idleWorkers = gameState.updatingCollection("idle-workers-base-" + this.ID, filter, this.workers).values();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ m.getMaxStrength = function(ent, againstClass)
|
|||
case "pierce":
|
||||
strength += (val * 0.065) / 3;
|
||||
break;
|
||||
default:
|
||||
API3.warn("Petra: " + str + " unknown attackStrength in getMaxStrength");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +52,8 @@ m.getMaxStrength = function(ent, againstClass)
|
|||
case "prepare":
|
||||
strength -= (val / 100000);
|
||||
break;
|
||||
default:
|
||||
API3.warn("Petra: " + str + " unknown attackTimes in getMaxStrength");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -69,6 +73,8 @@ m.getMaxStrength = function(ent, againstClass)
|
|||
case "pierce":
|
||||
strength += (val * 0.065) / 3;
|
||||
break;
|
||||
default:
|
||||
API3.warn("Petra: " + str + " unknown armourStrength in getMaxStrength");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ m.QueueManager.prototype.distributeResources = function(gameState)
|
|||
var total = gameState.getResources()[res];
|
||||
var scale = total / (total - availableRes[res]);
|
||||
availableRes[res] = total;
|
||||
for (var j in this.queues)
|
||||
for (let j in this.queues)
|
||||
{
|
||||
this.accounts[j][res] = Math.floor(scale * this.accounts[j][res]);
|
||||
availableRes[res] -= this.accounts[j][res];
|
||||
|
|
@ -255,7 +255,7 @@ m.QueueManager.prototype.distributeResources = function(gameState)
|
|||
// -queues accounts are capped at "resources for the first + 60% of the next"
|
||||
// This avoids getting a high priority queue with many elements hogging all of one resource
|
||||
// uselessly while it awaits for other resources.
|
||||
for (var j in this.queues)
|
||||
for (let j in this.queues)
|
||||
{
|
||||
// returns exactly the correct amount, ie 0 if we're not go.
|
||||
var queueCost = this.queues[j].maxAccountWanted(gameState, 0.6);
|
||||
|
|
@ -281,10 +281,10 @@ m.QueueManager.prototype.distributeResources = function(gameState)
|
|||
// But we'll sometimes allow less if that would overflow.
|
||||
var available = availableRes[res];
|
||||
var missing = false;
|
||||
for (var j in tempPrio)
|
||||
for (let j in tempPrio)
|
||||
{
|
||||
// we'll add at much what can be allowed to this queue.
|
||||
var toAdd = Math.floor(availableRes[res] * tempPrio[j]/totalPriority);
|
||||
let toAdd = Math.floor(availableRes[res] * tempPrio[j]/totalPriority);
|
||||
if (toAdd >= maxNeed[j])
|
||||
toAdd = maxNeed[j];
|
||||
else
|
||||
|
|
@ -295,9 +295,9 @@ m.QueueManager.prototype.distributeResources = function(gameState)
|
|||
}
|
||||
if (missing && available > 0) // distribute the rest (due to floor) in any queue
|
||||
{
|
||||
for (var j in tempPrio)
|
||||
for (let j in tempPrio)
|
||||
{
|
||||
var toAdd = Math.min(maxNeed[j], available);
|
||||
let toAdd = Math.min(maxNeed[j], available);
|
||||
this.accounts[j][res] += toAdd;
|
||||
available -= toAdd;
|
||||
if (available <= 0)
|
||||
|
|
@ -423,12 +423,12 @@ m.QueueManager.prototype.checkPausedQueues = function(gameState)
|
|||
else if (numWorkers < workersMin / 3)
|
||||
toBePaused = (q !== "citizenSoldier" && q !== "villager" && q !== "emergency");
|
||||
else if (numWorkers < workersMin * 2 / 3)
|
||||
toBePaused = (q === "civilCentre" || q === "economicBuilding"
|
||||
|| q === "militaryBuilding" || q === "defenseBuilding"
|
||||
|| q === "majorTech" || q === "minorTech" || q.indexOf("plan_") !== -1);
|
||||
toBePaused = (q === "civilCentre" || q === "economicBuilding" ||
|
||||
q === "militaryBuilding" || q === "defenseBuilding" ||
|
||||
q === "majorTech" || q === "minorTech" || q.indexOf("plan_") !== -1);
|
||||
else if (numWorkers < workersMin)
|
||||
toBePaused = (q === "civilCentre" || q === "defenseBuilding"
|
||||
|| q == "majorTech" || q.indexOf("_siege") != -1 || q.indexOf("_champ") != -1);
|
||||
toBePaused = (q === "civilCentre" || q === "defenseBuilding" ||
|
||||
q == "majorTech" || q.indexOf("_siege") != -1 || q.indexOf("_champ") != -1);
|
||||
|
||||
let queue = this.queues[q];
|
||||
if (!queue.paused && toBePaused)
|
||||
|
|
@ -547,8 +547,8 @@ m.QueueManager.prototype.Serialize = function()
|
|||
queues[q] = this.queues[q].Serialize();
|
||||
accounts[q] = this.accounts[q].Serialize();
|
||||
if (this.Config.debug == -100)
|
||||
API3.warn("queueManager serialization: queue " + q + " >>> " + uneval(queues[q])
|
||||
+ " with accounts " + uneval(accounts[q]));
|
||||
API3.warn("queueManager serialization: queue " + q + " >>> " +
|
||||
uneval(queues[q]) + " with accounts " + uneval(accounts[q]));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -25,48 +25,45 @@ m.TrainingPlan.prototype.canStart = function(gameState)
|
|||
if (this.invalidTemplate)
|
||||
return false;
|
||||
|
||||
// TODO: we should probably check pop caps
|
||||
|
||||
let trainers = gameState.findTrainers(this.type);
|
||||
if (this.metadata && this.metadata.sea)
|
||||
var trainers = gameState.findTrainers(this.type).filter(API3.Filters.byMetadata(PlayerID, "sea", this.metadata.sea));
|
||||
else
|
||||
var trainers = gameState.findTrainers(this.type);
|
||||
trainers = trainers.filter(API3.Filters.byMetadata(PlayerID, "sea", this.metadata.sea));
|
||||
|
||||
return (trainers.length != 0);
|
||||
return (trainers.length !== 0);
|
||||
};
|
||||
|
||||
m.TrainingPlan.prototype.start = function(gameState)
|
||||
{
|
||||
if (this.metadata && this.metadata.trainer)
|
||||
{
|
||||
var metadata = {};
|
||||
for (var key in this.metadata)
|
||||
let metadata = {};
|
||||
for (let key in this.metadata)
|
||||
if (key !== "trainer")
|
||||
metadata[key] = this.metadata[key];
|
||||
var trainer = gameState.getEntityById(this.metadata.trainer);
|
||||
let trainer = gameState.getEntityById(this.metadata.trainer);
|
||||
if (trainer)
|
||||
trainer.train(gameState.civ(), this.type, this.number, metadata, this.promotedTypes(gameState));
|
||||
this.onStart(gameState);
|
||||
return;
|
||||
}
|
||||
|
||||
let trainersColl = gameState.findTrainers(this.type);
|
||||
if (this.metadata && this.metadata.sea)
|
||||
var trainers = gameState.findTrainers(this.type).filter(API3.Filters.byMetadata(PlayerID, "sea", this.metadata.sea)).toEntityArray();
|
||||
trainersColl = trainersColl.filter(API3.Filters.byMetadata(PlayerID, "sea", this.metadata.sea));
|
||||
else if (this.metadata && this.metadata.base)
|
||||
var trainers = gameState.findTrainers(this.type).filter(API3.Filters.byMetadata(PlayerID, "base", this.metadata.base)).toEntityArray();
|
||||
else
|
||||
var trainers = gameState.findTrainers(this.type).toEntityArray();
|
||||
trainersColl = trainersColl.filter(API3.Filters.byMetadata(PlayerID, "base", this.metadata.base));
|
||||
|
||||
// Prefer training buildings with short queues
|
||||
// (TODO: this should also account for units added to the queue by
|
||||
// plans that have already been executed this turn)
|
||||
if (trainers.length > 0)
|
||||
if (trainersColl.length > 0)
|
||||
{
|
||||
var wantedIndex = undefined;
|
||||
let trainers = trainersColl.toEntityArray();
|
||||
let wantedIndex;
|
||||
if (this.metadata && this.metadata.index)
|
||||
wantedIndex = this.metadata.index;
|
||||
var workerUnit = (this.metadata && this.metadata.role && this.metadata.role == "worker");
|
||||
var supportUnit = this.template.hasClass("Support");
|
||||
let workerUnit = (this.metadata && this.metadata.role && this.metadata.role == "worker");
|
||||
let supportUnit = this.template.hasClass("Support");
|
||||
trainers.sort(function(a, b) {
|
||||
let aa = a.trainingQueueTime();
|
||||
let bb = b.trainingQueueTime();
|
||||
|
|
@ -102,7 +99,7 @@ m.TrainingPlan.prototype.start = function(gameState)
|
|||
}
|
||||
return (aa - bb);
|
||||
});
|
||||
if (this.metadata && this.metadata.base !== undefined && this.metadata.base == 0)
|
||||
if (this.metadata && this.metadata.base !== undefined && this.metadata.base === 0)
|
||||
this.metadata.base = trainers[0].getMetadata(PlayerID, "base");
|
||||
trainers[0].train(gameState.civ(), this.type, this.number, this.metadata, this.promotedTypes(gameState));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,18 +54,20 @@ m.TradeManager.prototype.trainMoreTraders = function(gameState, queues)
|
|||
numLandTraders += item.count;
|
||||
});
|
||||
});
|
||||
if (numTraders >= this.targetNumTraders
|
||||
&& ((!this.tradeRoute.sea && numLandTraders >= Math.floor(this.targetNumTraders/2))
|
||||
|| (this.tradeRoute.sea && numSeaTraders >= Math.floor(this.targetNumTraders/2))))
|
||||
if (numTraders >= this.targetNumTraders &&
|
||||
((!this.tradeRoute.sea && numLandTraders >= Math.floor(this.targetNumTraders/2)) ||
|
||||
(this.tradeRoute.sea && numSeaTraders >= Math.floor(this.targetNumTraders/2))))
|
||||
return;
|
||||
|
||||
let template;
|
||||
let metadata = { "role": "trader" };
|
||||
if (this.tradeRoute.sea)
|
||||
{
|
||||
// if we have some merchand ships affected to transport, try first to reaffect them
|
||||
// May-be, there were produced at an early stage when no other ship were available
|
||||
// and the naval manager will train now more appropriate ships.
|
||||
var already = false;
|
||||
var shipToSwitch;
|
||||
let already = false;
|
||||
let shipToSwitch;
|
||||
gameState.ai.HQ.navalManager.seaTransportShips[this.tradeRoute.sea].forEach(function(ship) {
|
||||
if (already || !ship.hasClass("Trader"))
|
||||
return;
|
||||
|
|
@ -87,16 +89,16 @@ m.TradeManager.prototype.trainMoreTraders = function(gameState, queues)
|
|||
return;
|
||||
}
|
||||
|
||||
var template = gameState.applyCiv("units/{civ}_ship_merchant");
|
||||
var metadata = { "role": "trader", "sea": this.tradeRoute.sea };
|
||||
template = gameState.applyCiv("units/{civ}_ship_merchant");
|
||||
metadata.sea = this.tradeRoute.sea;
|
||||
}
|
||||
else
|
||||
{
|
||||
var template = gameState.applyCiv("units/{civ}_support_trader");
|
||||
template = gameState.applyCiv("units/{civ}_support_trader");
|
||||
if (!this.tradeRoute.source.hasClass("NavalMarket"))
|
||||
var metadata = { "role": "trader", "base": this.tradeRoute.source.getMetadata(PlayerID, "base") };
|
||||
metadata.base = this.tradeRoute.source.getMetadata(PlayerID, "base");
|
||||
else
|
||||
var metadata = { "role": "trader", "base": this.tradeRoute.target.getMetadata(PlayerID, "base") };
|
||||
metadata.base = this.tradeRoute.target.getMetadata(PlayerID, "base");
|
||||
}
|
||||
|
||||
if (!gameState.getTemplate(template))
|
||||
|
|
@ -116,10 +118,7 @@ m.TradeManager.prototype.updateTrader = function(gameState, ent)
|
|||
return;
|
||||
|
||||
Engine.ProfileStart("Trade Manager");
|
||||
if (ent.hasClass("Ship"))
|
||||
var access = ent.getMetadata(PlayerID, "sea");
|
||||
else
|
||||
var access = gameState.ai.accessibility.getAccessValue(ent.position());
|
||||
var access = ent.hasClass("Ship") ? ent.getMetadata(PlayerID, "sea") : gameState.ai.accessibility.getAccessValue(ent.position());
|
||||
var route = this.checkRoutes(gameState, access);
|
||||
if (!route)
|
||||
{
|
||||
|
|
@ -215,27 +214,28 @@ m.TradeManager.prototype.performBarter = function(gameState)
|
|||
|
||||
var prices = gameState.getBarterPrices();
|
||||
// calculates conversion rates
|
||||
var getBarterRate = function (prices,buy,sell) { return Math.round(100 * prices["sell"][sell] / prices["buy"][buy]); };
|
||||
var getBarterRate = function (prices,buy,sell) { return Math.round(100 * prices.sell[sell] / prices.buy[buy]); };
|
||||
|
||||
// loop through each missing resource checking if we could barter and help finishing a queue quickly.
|
||||
for (var buy of needs.types)
|
||||
{
|
||||
if (needs[buy] == 0 || needs[buy] < rates[buy]*30) // check if our rate allows to gather it fast enough
|
||||
if (needs[buy] === 0 || needs[buy] < rates[buy]*30) // check if our rate allows to gather it fast enough
|
||||
continue;
|
||||
|
||||
// pick the best resource to barter.
|
||||
var bestToSell = undefined;
|
||||
var bestRate = 0;
|
||||
for (var sell of needs.types)
|
||||
for (let sell of needs.types)
|
||||
{
|
||||
if (sell === buy)
|
||||
continue;
|
||||
if (needs[sell] > 0 || available[sell] < 500) // do not sell if we need it or do not have enough buffer
|
||||
continue;
|
||||
|
||||
let barterRateMin;
|
||||
if (sell === "food")
|
||||
{
|
||||
var barterRateMin = 30;
|
||||
barterRateMin = 30;
|
||||
if (available[sell] > 40000)
|
||||
barterRateMin = 0;
|
||||
else if (available[sell] > 15000)
|
||||
|
|
@ -245,14 +245,14 @@ m.TradeManager.prototype.performBarter = function(gameState)
|
|||
}
|
||||
else
|
||||
{
|
||||
var barterRateMin = 70;
|
||||
barterRateMin = 70;
|
||||
if (available[sell] > 1000)
|
||||
barterRateMin = 50;
|
||||
if (buy === "food")
|
||||
barterRateMin += 20;
|
||||
}
|
||||
|
||||
var barterRate = getBarterRate(prices, buy, sell);
|
||||
let barterRate = getBarterRate(prices, buy, sell);
|
||||
if (barterRate > bestRate && barterRate > barterRateMin)
|
||||
{
|
||||
bestRate = barterRate;
|
||||
|
|
@ -263,29 +263,29 @@ m.TradeManager.prototype.performBarter = function(gameState)
|
|||
{
|
||||
barterers[0].barter(buy, bestToSell, 100);
|
||||
if (this.Config.debug > 2)
|
||||
API3.warn("Necessity bartering: sold " + bestToSell +" for " + buy + " >> need sell " + needs[bestToSell]
|
||||
+ " need buy " + needs[buy] + " rate buy " + rates[buy] + " available sell " + available[bestToSell]
|
||||
+ " available buy " + available[buy] + " barterRate " + bestRate);
|
||||
API3.warn("Necessity bartering: sold " + bestToSell +" for " + buy + " >> need sell " + needs[bestToSell] +
|
||||
" need buy " + needs[buy] + " rate buy " + rates[buy] + " available sell " + available[bestToSell] +
|
||||
" available buy " + available[buy] + " barterRate " + bestRate);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// now do contingency bartering, selling food to buy finite resources (and annoy our ennemies by increasing prices)
|
||||
if (available["food"] < 1000 || needs["food"] > 0)
|
||||
if (available.food < 1000 || needs.food > 0)
|
||||
return false;
|
||||
var bestToBuy;
|
||||
var bestChoice = 0;
|
||||
for (var buy of needs.types)
|
||||
for (let buy of needs.types)
|
||||
{
|
||||
if (buy === "food")
|
||||
continue;
|
||||
var barterRateMin = 80;
|
||||
if (available[buy] < 5000 && available["food"] > 5000)
|
||||
let barterRateMin = 80;
|
||||
if (available[buy] < 5000 && available.food > 5000)
|
||||
barterRateMin -= (20 - Math.floor(available[buy]/250));
|
||||
var barterRate = getBarterRate(prices, buy, "food");
|
||||
let barterRate = getBarterRate(prices, buy, "food");
|
||||
if (barterRate < barterRateMin)
|
||||
continue;
|
||||
var choice = barterRate / (100 + available[buy]);
|
||||
let choice = barterRate / (100 + available[buy]);
|
||||
if (choice > bestChoice)
|
||||
{
|
||||
bestChoice = choice;
|
||||
|
|
@ -296,8 +296,8 @@ m.TradeManager.prototype.performBarter = function(gameState)
|
|||
{
|
||||
barterers[0].barter(bestToBuy, "food", 100);
|
||||
if (this.Config.debug > 2)
|
||||
API3.warn("Contingency bartering: sold food for " + bestToBuy + " available sell " + available["food"]
|
||||
+ " available buy " + available[bestToBuy] + " barterRate " + getBarterRate(prices, bestToBuy, "food"));
|
||||
API3.warn("Contingency bartering: sold food for " + bestToBuy + " available sell " + available["food"] +
|
||||
" available buy " + available[bestToBuy] + " barterRate " + getBarterRate(prices, bestToBuy, "food"));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ m.TradeManager.prototype.checkRoutes = function(gameState, accessIndex)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (market2.length == 0)
|
||||
if (!market2.length)
|
||||
market2 = market1;
|
||||
var candidate = { "gain": 0 };
|
||||
var potential = { "gain": 0 };
|
||||
|
|
@ -468,7 +468,7 @@ m.TradeManager.prototype.checkRoutes = function(gameState, accessIndex)
|
|||
|
||||
if (this.Config.chat)
|
||||
{
|
||||
var owner = this.tradeRoute.source.owner();
|
||||
let owner = this.tradeRoute.source.owner();
|
||||
if (owner === PlayerID)
|
||||
owner = this.tradeRoute.target.owner();
|
||||
if (owner !== PlayerID && !this.warnedAllies[owner])
|
||||
|
|
@ -505,15 +505,12 @@ m.TradeManager.prototype.checkTrader = function(gameState, ent)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ent.hasClass("Ship"))
|
||||
var access = ent.getMetadata(PlayerID, "sea");
|
||||
else
|
||||
var access = gameState.ai.accessibility.getAccessValue(ent.position());
|
||||
var access = ent.hasClass("Ship") ? ent.getMetadata(PlayerID, "sea") : gameState.ai.accessibility.getAccessValue(ent.position());
|
||||
var possibleRoute = this.checkRoutes(gameState, access);
|
||||
// Warning: presentRoute is from metadata, so contains entity ids
|
||||
if (!possibleRoute
|
||||
|| (possibleRoute.source.id() != presentRoute.source && possibleRoute.source.id() != presentRoute.target)
|
||||
|| (possibleRoute.target.id() != presentRoute.source && possibleRoute.target.id() != presentRoute.target))
|
||||
if (!possibleRoute ||
|
||||
(possibleRoute.source.id() != presentRoute.source && possibleRoute.source.id() != presentRoute.target) ||
|
||||
(possibleRoute.target.id() != presentRoute.source && possibleRoute.target.id() != presentRoute.target))
|
||||
{
|
||||
// Trader will be assigned in updateTrader
|
||||
ent.stopMoving();
|
||||
|
|
@ -535,7 +532,7 @@ m.TradeManager.prototype.prospectForNewMarket = function(gameState, queues)
|
|||
return;
|
||||
this.checkRoutes(gameState);
|
||||
var marketPos = gameState.ai.HQ.findMarketLocation(gameState, template);
|
||||
if (!marketPos || marketPos[3] == 0) // marketPos[3] is the expected gain
|
||||
if (!marketPos || marketPos[3] === 0) // marketPos[3] is the expected gain
|
||||
{ // no position found
|
||||
gameState.ai.HQ.stopBuild(gameState, "structures/{civ}_market");
|
||||
return;
|
||||
|
|
@ -547,11 +544,11 @@ m.TradeManager.prototype.prospectForNewMarket = function(gameState, queues)
|
|||
if (this.Config.debug > 1)
|
||||
{
|
||||
if (this.potentialTradeRoute)
|
||||
API3.warn("turn " + gameState.ai.playedTurn + "we could have a new route with gain "
|
||||
+ marketPos[3] + " instead of the present " + this.potentialTradeRoute.gain);
|
||||
API3.warn("turn " + gameState.ai.playedTurn + "we could have a new route with gain " +
|
||||
marketPos[3] + " instead of the present " + this.potentialTradeRoute.gain);
|
||||
else
|
||||
API3.warn("turn " + gameState.ai.playedTurn + "we could have a first route with gain "
|
||||
+ marketPos[3]);
|
||||
API3.warn("turn " + gameState.ai.playedTurn + "we could have a first route with gain " +
|
||||
marketPos[3]);
|
||||
}
|
||||
|
||||
if (!this.tradeRoute)
|
||||
|
|
@ -564,8 +561,8 @@ m.TradeManager.prototype.prospectForNewMarket = function(gameState, queues)
|
|||
|
||||
m.TradeManager.prototype.isNewMarketWorth = function(expectedGain)
|
||||
{
|
||||
if (this.potentialTradeRoute && expectedGain < 2*this.potentialTradeRoute.gain
|
||||
&& expectedGain < this.potentialTradeRoute.gain + 20)
|
||||
if (this.potentialTradeRoute && expectedGain < 2*this.potentialTradeRoute.gain &&
|
||||
expectedGain < this.potentialTradeRoute.gain + 20)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
|
@ -588,11 +585,11 @@ m.TradeManager.prototype.update = function(gameState, events, queues)
|
|||
if (this.tradeRoute)
|
||||
{
|
||||
this.traders.forEach(function(ent) { self.updateTrader(gameState, ent); });
|
||||
if (gameState.ai.playedTurn % 5 == 0)
|
||||
if (gameState.ai.playedTurn % 5 === 0)
|
||||
this.trainMoreTraders(gameState, queues);
|
||||
if (gameState.ai.playedTurn % 20 == 0 && this.traders.length >= 2)
|
||||
if (gameState.ai.playedTurn % 20 === 0 && this.traders.length >= 2)
|
||||
gameState.ai.HQ.researchManager.researchTradeBonus(gameState, queues);
|
||||
if (gameState.ai.playedTurn % 60 == 0)
|
||||
if (gameState.ai.playedTurn % 60 === 0)
|
||||
this.setTradingGoods(gameState);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ m.TransportPlan = function(gameState, units, startIndex, endIndex, endPos, ship)
|
|||
}
|
||||
|
||||
if (this.debug > 1)
|
||||
API3.warn("Starting a new transport plan with ID " + this.ID + " to index " + endIndex
|
||||
+ " with units length " + units.length);
|
||||
API3.warn("Starting a new transport plan with ID " + this.ID +
|
||||
" to index " + endIndex + " with units length " + units.length);
|
||||
|
||||
this.state = "boarding";
|
||||
this.boardingPos = {};
|
||||
|
|
@ -102,8 +102,8 @@ m.TransportPlan.prototype.countFreeSlotsOnShip = function(ship)
|
|||
{
|
||||
if (ship.hitpoints() < ship.garrisonEjectHealth() * ship.maxHitpoints())
|
||||
return 0;
|
||||
let occupied = ship.garrisoned().length
|
||||
+ this.units.filter(API3.Filters.byMetadata(PlayerID, "onBoard", ship.id())).length;
|
||||
let occupied = ship.garrisoned().length +
|
||||
this.units.filter(API3.Filters.byMetadata(PlayerID, "onBoard", ship.id())).length;
|
||||
return Math.max(ship.garrisonMax() - occupied, 0);
|
||||
};
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ m.TransportPlan.prototype.assignUnitToShip = function(gameState, ent)
|
|||
|
||||
for (let ship of this.transportShips.values())
|
||||
{
|
||||
if (this.countFreeSlotsOnShip(ship) == 0)
|
||||
if (this.countFreeSlotsOnShip(ship) === 0)
|
||||
continue;
|
||||
ent.setMetadata(PlayerID, "onBoard", ship.id());
|
||||
if (this.debug > 1)
|
||||
|
|
@ -386,7 +386,7 @@ m.TransportPlan.prototype.getBoardingPos = function(gameState, ship, landIndex,
|
|||
if (avoidEnnemy)
|
||||
{
|
||||
let territoryOwner = gameState.ai.HQ.territoryMap.getOwner(pos);
|
||||
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner))
|
||||
if (territoryOwner !== 0 && !gameState.isPlayerAlly(territoryOwner))
|
||||
dist += 100000000;
|
||||
}
|
||||
// require a small distance between all ships of the transport plan to avoid path finder problems
|
||||
|
|
|
|||
Loading…
Reference in a new issue