Petra: improve choice of ships to train and some style cleaning

This was SVN commit r15314.
This commit is contained in:
mimo
2014-06-09 07:54:59 +00:00
parent 5f42834710
commit 2c0daaf80b
9 changed files with 91 additions and 50 deletions
@@ -204,7 +204,7 @@ m.AttackManager.prototype.update = function(gameState, queues, events)
if (this.upcomingAttacks["Raid"].length === 0 && gameState.ai.HQ.defenseManager.targetList.length)
{
var target = undefined;
for each (var targetId in gameState.ai.HQ.defenseManager.targetList)
for (var targetId of gameState.ai.HQ.defenseManager.targetList)
{
target = gameState.getEntityById(targetId);
if (target)
@@ -498,7 +498,7 @@ m.AttackPlan.prototype.trainMoreUnits = function(gameState)
{
warn("====================================");
warn("======== build order for plan " + this.name);
for each (var order in this.buildOrder)
for (var order of this.buildOrder)
{
var specialData = "Plan_"+this.name+"_"+order[4];
var inTraining = gameState.countOwnQueuedEntitiesWithMetadata("special", specialData);
@@ -687,7 +687,7 @@ m.AttackPlan.prototype.rushTargetFinder = function(gameState)
var minDist = Math.min();
var target = undefined;
for each (var building in buildings)
for (var building of buildings)
{
if (building.owner() === 0)
continue;
@@ -696,7 +696,7 @@ m.AttackPlan.prototype.rushTargetFinder = function(gameState)
continue;
var pos = building.position();
var defended = false;
for each (var defense in buildings)
for (var defense of buildings)
{
if (!defense.hasClass("CivCentre") && !defense.hasClass("Tower") && !defense.hasClass("Fortress"))
continue;
@@ -728,7 +728,7 @@ m.AttackPlan.prototype.rushTargetFinder = function(gameState)
m.AttackPlan.prototype.raidTargetFinder = function(gameState)
{
var targets = new API3.EntityCollection(gameState.sharedScript);
for each (var targetId in gameState.ai.HQ.defenseManager.targetList)
for (var targetId of gameState.ai.HQ.defenseManager.targetList)
{
var target = gameState.getEntityById(targetId);
if (target && target.position())
@@ -1144,7 +1144,7 @@ m.AttackPlan.prototype.update = function(gameState, events)
{
// if siege units are attacked, we'll send some units to deal with enemies.
var collec = this.unitCollection.filter(API3.Filters.not(API3.Filters.byClass("Siege"))).filterNearest(ourUnit.position(), 5).toEntityArray();
for each (var ent in collec)
for (var ent of collec)
if (!this.isSiegeUnit(gameState, ent))
ent.attack(attacker.id());
}
@@ -1422,7 +1422,7 @@ m.AttackPlan.prototype.hasForceOrder = function(data, value)
if (data && +(ent.getMetadata(PlayerID, data)) !== value)
return;
var orders = ent.unitAIOrderData();
for each (var order in orders)
for (var order of orders)
if (order.force)
forced = true;
});
@@ -51,7 +51,7 @@ m.BaseManager.prototype.init = function(gameState, unconstructed)
this.dropsites = {};
this.dropsiteSupplies = {};
this.gatherers = {};
for each (var type in this.Config.resources)
for (var type of this.Config.resources)
{
this.dropsiteSupplies[type] = {"nearby": [], "medium": [], "faraway": []};
this.gatherers[type] = {"nextCheck": 0, "used": 0, "lost": 0};
@@ -343,7 +343,7 @@ m.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource)
if (total == 0)
continue;
for each (var cc in ccEnts)
for (var cc of ccEnts)
{
var ccPos = cc.position();
if (!ccPos)
@@ -381,7 +381,7 @@ m.BaseManager.prototype.getResourceLevel = function (gameState, type)
var count = 0;
var check = {};
var nearby = this.dropsiteSupplies[type]["nearby"];
for each (var supply in nearby)
for (var supply of nearby)
{
if (check[supply.id]) // avoid double counting as same resource can appear several time
continue;
@@ -389,7 +389,7 @@ m.BaseManager.prototype.getResourceLevel = function (gameState, type)
count += supply.ent.resourceSupplyAmount();
}
var medium = this.dropsiteSupplies[type]["medium"];
for each (var supply in medium)
for (var supply of medium)
{
if (check[supply.id])
continue;
@@ -402,7 +402,7 @@ m.BaseManager.prototype.getResourceLevel = function (gameState, type)
// check our resource levels and react accordingly
m.BaseManager.prototype.checkResourceLevels = function (gameState, queues)
{
for each (var type in this.Config.resources)
for (var type of this.Config.resources)
{
if (type == "food")
{
@@ -543,12 +543,12 @@ m.BaseManager.prototype.setWorkersIdleByPriority = function(gameState)
var resources = gameState.ai.queueManager.getAvailableResources(gameState);
var avgOverdraft = 0;
for each (var type in resources.types)
for (var type of resources.types)
avgOverdraft += resources[type];
avgOverdraft /= 4;
var mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState);
for each (var type in resources.types)
for (var type of resources.types)
{
if (type === mostNeeded[0])
continue;
@@ -1,6 +1,6 @@
{
"name": "Petra Bot",
"description": "Based on Aegis, but heavily modified and expected to be more robust. Support for naval maps is also added. Note that it doesn't support saved games yet and is not as well tested as Aegis. Please report issues to Wildfire Games (see the link in the main menu).",
"description": "Based on Aegis, but heavily modified by mimo and expected to be more robust. Support for naval maps is also added. Note that it doesn't support saved games yet. Please report issues to Wildfire Games (see the link in the main menu).",
"moduleName" : "PETRA",
"constructor": "PetraBot",
"useShared": true
@@ -25,7 +25,7 @@ m.DefenseArmy.prototype.assignUnit = function (gameState, entID)
var distMin = undefined;
var idMinAll = undefined;
var distMinAll = undefined;
for each (var id in this.foeEntities)
for (var id of this.foeEntities)
{
var eEnt = gameState.getEntityById(id);
if (!eEnt || !eEnt.position()) // probably can't happen.
@@ -95,7 +95,7 @@ m.DefenseArmy.prototype.getState = function (gameState)
m.DefenseArmy.prototype.update = function (gameState)
{
for each (var entId in this.ownEntities)
for (var entId of this.ownEntities)
{
var ent = gameState.getEntityById(entId);
if (!ent)
@@ -118,7 +118,7 @@ m.DefenseArmy.prototype.debug = function (gameState)
// m.debug ("Strength " + this.foeStrength);
// debug (gameState.getEntityById(ent)._templateName + ", ID " + ent);
//debug ("Defenders " + this.ownEntities.length);
for each (ent in this.foeEntities)
for (var ent of this.foeEntities)
{
if (gameState.getEntityById(ent) !== undefined)
{
@@ -117,12 +117,15 @@ m.createObstructionMap = function(gameState, accessIndex, template)
var map = new API3.Map(gameState.sharedScript, obstructionTiles);
map.setMaxVal(255);
if (template && template.buildDistance()) {
if (template && template.buildDistance())
{
var minDist = template.buildDistance().MinDistance;
var category = template.buildDistance().FromCategory;
if (minDist !== undefined && category !== undefined){
if (minDist !== undefined && category !== undefined)
{
gameState.getOwnStructures().forEach(function(ent) {
if (ent.buildCategory() === category && ent.position()){
if (ent.buildCategory() === category && ent.position())
{
var pos = ent.position();
var x = Math.round(pos[0] / gameState.cellSize);
var z = Math.round(pos[1] / gameState.cellSize);
@@ -288,7 +288,7 @@ m.NavalManager.prototype.requireTransport = function(gameState, entity, startInd
return false;
}
for each (var plan in this.transportPlans)
for (var plan of this.transportPlans)
{
if (plan.startIndex !== startIndex || plan.endIndex !== endIndex)
continue
@@ -328,7 +328,7 @@ m.NavalManager.prototype.checkLevels = function(gameState, queues)
for (var sea = 0; sea < this.neededTransportShips.length; sea++)
this.neededTransportShips[sea] = 0;
for each (var plan in this.transportPlans)
for (var plan of this.transportPlans)
{
if (!plan.needTransportShips || plan.units.length < 2)
continue;
@@ -357,30 +357,29 @@ m.NavalManager.prototype.maintainFleet = function(gameState, queues)
gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_super_dock"), true) === 0)
return;
// check if we have enough transport ships per region.
for (var i = 0; i < this.seaShips.length; ++i)
for (var sea = 0; sea < this.seaShips.length; ++sea)
{
if (this.accessibleSeas.indexOf(i) === -1)
if (this.accessibleSeas.indexOf(sea) === -1)
continue;
if (gameState.countOwnQueuedEntitiesWithMetadata("sea", i) > 0)
if (gameState.countOwnQueuedEntitiesWithMetadata("sea", sea) > 0)
continue;
if (this.seaTransportShips[i].length < this.wantedTransportShips[i])
if (this.seaTransportShips[sea].length < this.wantedTransportShips[sea])
{
if ((gameState.civ() === "cart" && gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_super_dock"), true) === 0)
|| gameState.civ() === "iber")
queues.ships.addItem(new m.TrainingPlan(gameState, "units/{civ}_ship_merchant", { "sea": i }, 1, 1));
else
queues.ships.addItem(new m.TrainingPlan(gameState, "units/{civ}_ship_trireme", { "sea": i }, 1, 1));
var template = this.getBestShip(gameState, sea, "transport");
if (!template)
continue;
queues.ships.addItem(new m.TrainingPlan(gameState, template, { "sea": sea }, 1, 1));
}
else if (this.seaFishShips[i].length < this.wantedFishShips[i])
queues.ships.addItem(new m.TrainingPlan(gameState, "units/{civ}_ship_fishing", { "base": 0, "role": "worker", "sea": i }, 1, 1));
else if (this.seaFishShips[sea].length < this.wantedFishShips[sea])
queues.ships.addItem(new m.TrainingPlan(gameState, "units/{civ}_ship_fishing", { "base": 0, "role": "worker", "sea": sea }, 1, 1));
}
};
// assigns free ships to plans that need some
m.NavalManager.prototype.assignToPlans = function(gameState)
{
for each (var plan in this.transportPlans)
for (var plan of this.transportPlans)
{
if (!plan.needTransportShips)
continue;
@@ -467,6 +466,47 @@ m.NavalManager.prototype.buildNavalStructures = function(gameState, queues)
}
};
// goal can be either attack (choose ship with best arrowCount) or transport (choose ship with best capacity)
m.NavalManager.prototype.getBestShip = function(gameState, sea, goal)
{
var trainableShips = [];
gameState.getOwnTrainingFacilities().filter(API3.Filters.byMetadata(PlayerID, "sea", sea)).forEach(function(ent) {
var trainables = ent.trainableEntities();
for (var trainable of trainables)
{
var template = gameState.getTemplate(trainable);
if (template.hasClass("Ship") && trainableShips.indexOf(trainable) === -1)
trainableShips.push(trainable);
}
});
var best = 0;
var bestShip = undefined;
for (var trainable of trainableShips)
{
var template = gameState.getTemplate(trainable);
var arrows = +(template.getDefaultArrow() || 0);
if (goal === "attack") // choose the maximum default arrows
{
if (best > arrows)
continue;
best = arrows;
}
else if (goal === "transport") // choose the maximum capacity, with a bonus if arrows or if siege transport
{
var capacity = +(template.garrisonMax() || 0);
capacity += 10*arrows;
if (MatchesClassList(template.garrisonableClasses(), "Siege"))
capacity += 50;
if (best > capacity)
continue;
best = capacity;
}
bestShip = trainable;
}
return bestShip;
};
m.NavalManager.prototype.update = function(gameState, queues, events)
{
Engine.ProfileStart("Naval Manager update");
@@ -393,14 +393,10 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
}
}
var radius = 1; // not used
if (bestVal === undefined || bestVal === -1)
{
var bestTile = friendlyTiles.findBestTile(radius, obstructionMap);
var bestIdx = bestTile[0];
var bestVal = bestTile[1];
}
var radius = 1;
var bestTile = friendlyTiles.findBestTile(radius, obstructionMap);
var bestIdx = bestTile[0];
var bestVal = bestTile[1];
if (bestVal <= 0)
return false;
@@ -463,10 +459,12 @@ m.ConstructionPlan.prototype.getDockAngle = function(gameState, template, x, z)
var seaAccess = gameState.ai.accessibility.navalPassMap[j];
var landAccess = gameState.ai.accessibility.landPassMap[j];
if (seaAccess === seaRef && landAccess < 2)
waterPoints.push(i);
waterPoints.push(i);
}
var consec = [];
var length = waterPoints.length;
if (!length)
continue;
var consec = [];
for (var i = 0; i < length; ++i)
{
var count = 0;
@@ -131,12 +131,12 @@ m.TradeManager.prototype.buildTradeRoute = function(gameState, queues)
var distmax = -1;
var imax = -1;
var jmax = -1;
for each (var m1 in market1)
for (var m1 of market1)
{
if (!m1.position())
continue;
var index1 = gameState.ai.accessibility.getAccessValue(m1.position());
for each (var m2 in market2)
for (var m2 of market2)
{
if (m1.id() === m2.id())
continue;
@@ -230,7 +230,7 @@ m.TradeManager.prototype.performBarter = function(gameState)
var getBarterRate = function (prices,buy,sell) { return Math.round(100 * prices["sell"][sell] / prices["buy"][buy]); };
// loop through each queues checking if we could barter and help finishing a queue quickly.
for each (var buy in needs.types)
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
continue;
@@ -238,7 +238,7 @@ m.TradeManager.prototype.performBarter = function(gameState)
// pick the best resource to barter.
var bestToSell = undefined;
var bestRate = 0;
for each (var sell in needs.types)
for (var sell of needs.types)
{
if (sell === buy)
continue;
@@ -287,7 +287,7 @@ m.TradeManager.prototype.performBarter = function(gameState)
return false;
var bestToBuy = undefined;
var bestChoice = 0;
for each (var buy in needs.types)
for (var buy of needs.types)
{
if (buy === "food")
continue;