2014-03-24 23:33:50 +01:00
|
|
|
var PETRA = function(m)
|
|
|
|
{
|
|
|
|
|
|
|
|
m.TrainingPlan = function(gameState, type, metadata, number, maxMerge)
|
|
|
|
{
|
|
|
|
if (!m.QueuePlan.call(this, gameState, type, metadata))
|
|
|
|
{
|
|
|
|
warn(" Plan training " + type + " canceled");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.category = "unit";
|
|
|
|
this.cost = new API3.Resources(this.template.cost(), this.template._template.Cost.Population);
|
|
|
|
|
|
|
|
this.number = number !== undefined ? number : 1;
|
|
|
|
this.maxMerge = maxMerge !== undefined ? maxMerge : 5;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
m.TrainingPlan.prototype = Object.create(m.QueuePlan.prototype);
|
|
|
|
|
|
|
|
m.TrainingPlan.prototype.canStart = function(gameState)
|
|
|
|
{
|
|
|
|
if (this.invalidTemplate)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// TODO: we should probably check pop caps
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
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);
|
2014-03-24 23:33:50 +01:00
|
|
|
|
|
|
|
return (trainers.length != 0);
|
|
|
|
};
|
|
|
|
|
|
|
|
m.TrainingPlan.prototype.start = function(gameState)
|
|
|
|
{
|
2014-06-15 14:57:12 +02:00
|
|
|
if (this.metadata && this.metadata.trainer)
|
|
|
|
{
|
|
|
|
var metadata = {};
|
|
|
|
for (var key in this.metadata)
|
|
|
|
if (key !== "trainer")
|
|
|
|
metadata[key] = this.metadata[key];
|
|
|
|
var trainer = gameState.getEntityById(this.metadata.trainer);
|
|
|
|
if (trainer)
|
2014-07-22 23:23:25 +02:00
|
|
|
trainer.train(this.type, this.number, metadata, this.promotedTypes(gameState));
|
2014-06-15 14:57:12 +02:00
|
|
|
this.onStart(gameState);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
if (this.metadata && this.metadata.sea)
|
|
|
|
var trainers = gameState.findTrainers(this.type).filter(API3.Filters.byMetadata(PlayerID, "sea", this.metadata.sea)).toEntityArray();
|
|
|
|
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();
|
2014-03-24 23:33:50 +01:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
{
|
2014-05-18 13:34:36 +02:00
|
|
|
var wantedIndex = undefined;
|
|
|
|
if (this.metadata && this.metadata.index)
|
|
|
|
wantedIndex = this.metadata.index;
|
2014-11-18 20:56:23 +01:00
|
|
|
var workerUnit = (this.metadata && this.metadata.role && this.metadata.role == "worker");
|
2014-05-18 13:34:36 +02:00
|
|
|
var supportUnit = this.template.hasClass("Support");
|
2014-03-24 23:33:50 +01:00
|
|
|
trainers.sort(function(a, b) {
|
2014-11-18 20:56:23 +01:00
|
|
|
let aa = a.trainingQueueTime();
|
|
|
|
let bb = b.trainingQueueTime();
|
2014-05-18 13:34:36 +02:00
|
|
|
if (a.hasClass("Civic") && !supportUnit)
|
2014-06-10 14:59:42 +02:00
|
|
|
aa += 10;
|
2014-05-18 13:34:36 +02:00
|
|
|
if (b.hasClass("Civic") && !supportUnit)
|
2014-06-10 14:59:42 +02:00
|
|
|
bb += 10;
|
2014-07-01 21:48:38 +02:00
|
|
|
if (supportUnit)
|
|
|
|
{
|
|
|
|
if (gameState.ai.HQ.isDangerousLocation(a.position()))
|
|
|
|
aa += 50;
|
2014-10-02 21:01:26 +02:00
|
|
|
if (gameState.ai.HQ.isDangerousLocation(b.position()))
|
2014-07-01 21:48:38 +02:00
|
|
|
bb += 50;
|
|
|
|
}
|
2014-11-18 20:56:23 +01:00
|
|
|
let aBase = a.getMetadata(PlayerID, "base");
|
|
|
|
let bBase = b.getMetadata(PlayerID, "base");
|
2014-05-18 13:34:36 +02:00
|
|
|
if (wantedIndex)
|
|
|
|
{
|
2014-11-18 20:56:23 +01:00
|
|
|
if (!aBase || gameState.ai.HQ.baseManagers[aBase].accessIndex != wantedIndex)
|
2014-06-10 14:59:42 +02:00
|
|
|
aa += 30;
|
2014-11-18 20:56:23 +01:00
|
|
|
if (!bBase || gameState.ai.HQ.baseManagers[bBase].accessIndex != wantedIndex)
|
2014-06-10 14:59:42 +02:00
|
|
|
bb += 30;
|
2014-05-18 13:34:36 +02:00
|
|
|
}
|
2014-11-18 20:56:23 +01:00
|
|
|
// then, if worker, small preference for bases with less workers
|
|
|
|
if (workerUnit && aBase && bBase && aBase != bBase)
|
|
|
|
{
|
|
|
|
let apop = gameState.ai.HQ.baseManagers[aBase].workers.length;
|
|
|
|
let bpop = gameState.ai.HQ.baseManagers[bBase].workers.length;
|
|
|
|
if (apop > bpop)
|
|
|
|
aa++;
|
|
|
|
else if (bpop > apop)
|
|
|
|
bb++;
|
|
|
|
}
|
2014-03-24 23:33:50 +01:00
|
|
|
return (aa - bb);
|
|
|
|
});
|
2014-11-18 20:56:23 +01:00
|
|
|
if (this.metadata && this.metadata.base !== undefined && this.metadata.base == 0)
|
2014-05-18 13:34:36 +02:00
|
|
|
this.metadata.base = trainers[0].getMetadata(PlayerID, "base");
|
2014-07-22 23:23:25 +02:00
|
|
|
trainers[0].train(this.type, this.number, this.metadata, this.promotedTypes(gameState));
|
2014-03-24 23:33:50 +01:00
|
|
|
}
|
2014-11-05 22:03:25 +01:00
|
|
|
else if (gameState.ai.Config.debug > 1)
|
2014-03-26 22:07:47 +01:00
|
|
|
warn(" no trainers for this queue " + this.type);
|
2014-03-24 23:33:50 +01:00
|
|
|
this.onStart(gameState);
|
|
|
|
};
|
|
|
|
|
|
|
|
m.TrainingPlan.prototype.addItem = function(amount)
|
|
|
|
{
|
|
|
|
if (amount === undefined)
|
|
|
|
amount = 1;
|
|
|
|
this.number += amount;
|
|
|
|
};
|
|
|
|
|
2014-07-22 23:23:25 +02:00
|
|
|
// Find the promoted types corresponding to this.type
|
|
|
|
m.TrainingPlan.prototype.promotedTypes = function(gameState)
|
|
|
|
{
|
|
|
|
var types = [];
|
2014-08-28 10:01:25 +02:00
|
|
|
var promotion = this.template.promotion();
|
|
|
|
var previous;
|
2014-07-22 23:23:25 +02:00
|
|
|
while (promotion)
|
|
|
|
{
|
|
|
|
types.push(promotion);
|
2014-08-28 10:01:25 +02:00
|
|
|
previous = promotion;
|
|
|
|
promotion = gameState.getTemplate(promotion).promotion();
|
|
|
|
if (previous === promotion)
|
|
|
|
{
|
2014-11-05 22:03:25 +01:00
|
|
|
if (gameState.ai.Config.debug > 0)
|
2014-08-28 10:01:25 +02:00
|
|
|
API3.warn(" unit " + promotion + " is its own promoted unit");
|
|
|
|
promotion = undefined;
|
|
|
|
}
|
2014-07-22 23:23:25 +02:00
|
|
|
}
|
|
|
|
return types;
|
|
|
|
};
|
|
|
|
|
2014-11-10 10:03:03 +01:00
|
|
|
m.TrainingPlan.prototype.Serialize = function()
|
|
|
|
{
|
|
|
|
return {
|
|
|
|
"type": this.type,
|
|
|
|
"metadata": this.metadata,
|
|
|
|
"ID": this.ID,
|
|
|
|
"category": this.category,
|
|
|
|
"cost": this.cost.Serialize(),
|
|
|
|
"number": this.number,
|
|
|
|
"maxMerge": this.maxMerge,
|
|
|
|
"lastIsGo": this.lastIsGo
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
m.TrainingPlan.prototype.Deserialize = function(gameState, data)
|
|
|
|
{
|
|
|
|
for (let key in data)
|
|
|
|
this[key] = data[key];
|
|
|
|
|
|
|
|
let cost = new API3.Resources();
|
|
|
|
cost.Deserialize(data.cost);
|
|
|
|
this.cost = cost;
|
|
|
|
};
|
|
|
|
|
2014-03-24 23:33:50 +01:00
|
|
|
return m;
|
|
|
|
}(PETRA);
|