211 lines
4.5 KiB
JavaScript
211 lines
4.5 KiB
JavaScript
/**
|
|
* Provides an API for the rest of the AI scripts to query the world state
|
|
* at a higher level than the raw data.
|
|
*/
|
|
var GameState = Class({
|
|
|
|
_init: function(ai)
|
|
{
|
|
MemoizeInit(this);
|
|
|
|
this.ai = ai;
|
|
this.timeElapsed = ai.timeElapsed;
|
|
this.templates = ai.templates;
|
|
this.entities = ai.entities;
|
|
this.playerData = ai.playerData;
|
|
},
|
|
|
|
getTimeElapsed: function()
|
|
{
|
|
return this.timeElapsed;
|
|
},
|
|
|
|
getTemplate: function(type)
|
|
{
|
|
if (!this.templates[type])
|
|
return null;
|
|
return new EntityTemplate(this.templates[type]);
|
|
},
|
|
|
|
applyCiv: function(str)
|
|
{
|
|
return str.replace(/\{civ\}/g, this.playerData.civ);
|
|
},
|
|
|
|
displayCiv: function()
|
|
{
|
|
return this.playerData.civ;
|
|
},
|
|
|
|
getResources: function()
|
|
{
|
|
return new Resources(this.playerData.resourceCounts);
|
|
},
|
|
|
|
getMap: function()
|
|
{
|
|
return this.ai.map;
|
|
},
|
|
|
|
getPassabilityClassMask: function(name)
|
|
{
|
|
if (!(name in this.ai.passabilityClasses))
|
|
error("Tried to use invalid passability class name '"+name+"'");
|
|
return this.ai.passabilityClasses[name];
|
|
},
|
|
|
|
getOwnEntities: (function()
|
|
{
|
|
return new EntityCollection(this.ai, this.ai._ownEntities);
|
|
}),
|
|
|
|
getOwnEntitiesWithRole: Memoize('getOwnEntitiesWithRole', function(role)
|
|
{
|
|
var metas = this.ai._entityMetadata;
|
|
if (role === undefined)
|
|
return this.getOwnEntities().filter_raw(function(ent) {
|
|
var metadata = metas[ent.id];
|
|
if (!metadata || !('role' in metadata))
|
|
return true;
|
|
return (metadata.role === undefined);
|
|
});
|
|
else
|
|
return this.getOwnEntities().filter_raw(function(ent) {
|
|
var metadata = metas[ent.id];
|
|
if (!metadata || !('role' in metadata))
|
|
return false;
|
|
return (metadata.role === role);
|
|
});
|
|
}),
|
|
|
|
countEntitiesWithType: function(type)
|
|
{
|
|
var count = 0;
|
|
this.getOwnEntities().forEach(function(ent) {
|
|
var t = ent.templateName();
|
|
if (t == type)
|
|
++count;
|
|
});
|
|
return count;
|
|
},
|
|
|
|
countEntitiesAndQueuedWithType: function(type)
|
|
{
|
|
var foundationType = "foundation|" + type;
|
|
var count = 0;
|
|
this.getOwnEntities().forEach(function(ent) {
|
|
|
|
var t = ent.templateName();
|
|
if (t == type || t == foundationType)
|
|
++count;
|
|
|
|
var queue = ent.trainingQueue();
|
|
if (queue)
|
|
{
|
|
queue.forEach(function(item) {
|
|
if (item.template == type)
|
|
count += item.count;
|
|
});
|
|
}
|
|
});
|
|
return count;
|
|
},
|
|
|
|
countEntitiesAndQueuedWithRole: function(role)
|
|
{
|
|
var count = 0;
|
|
this.getOwnEntities().forEach(function(ent) {
|
|
|
|
if (ent.getMetadata("role") == role)
|
|
++count;
|
|
|
|
var queue = ent.trainingQueue();
|
|
if (queue)
|
|
{
|
|
queue.forEach(function(item) {
|
|
if (item.metadata && item.metadata.role == role)
|
|
count += item.count;
|
|
});
|
|
}
|
|
});
|
|
return count;
|
|
},
|
|
|
|
/**
|
|
* Find buildings that are capable of training the given unit type,
|
|
* and aren't already too busy.
|
|
*/
|
|
findTrainers: function(template)
|
|
{
|
|
var maxQueueLength = 3; // avoid tying up resources in giant training queues
|
|
|
|
return this.getOwnEntities().filter(function(ent) {
|
|
|
|
var trainable = ent.trainableEntities();
|
|
if (!trainable || trainable.indexOf(template) == -1)
|
|
return false;
|
|
|
|
var queue = ent.trainingQueue();
|
|
if (queue)
|
|
{
|
|
if (queue.length >= maxQueueLength)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Find units that are capable of constructing the given building type.
|
|
*/
|
|
findBuilders: function(template)
|
|
{
|
|
return this.getOwnEntities().filter(function(ent) {
|
|
|
|
var buildable = ent.buildableEntities();
|
|
if (!buildable || buildable.indexOf(template) == -1)
|
|
return false;
|
|
|
|
return true;
|
|
});
|
|
},
|
|
|
|
findFoundations: function(template)
|
|
{
|
|
return this.getOwnEntities().filter(function(ent) {
|
|
return (typeof ent.foundationProgress() !== "undefined");
|
|
});
|
|
},
|
|
|
|
findResourceSupplies: function()
|
|
{
|
|
var supplies = {};
|
|
this.entities.forEach(function(ent) {
|
|
var type = ent.resourceSupplyType();
|
|
if (!type)
|
|
return;
|
|
var amount = ent.resourceSupplyAmount();
|
|
if (!amount)
|
|
return;
|
|
|
|
var reportedType;
|
|
if (type.generic == "treasure")
|
|
reportedType = type.specific;
|
|
else
|
|
reportedType = type.generic;
|
|
|
|
if (!supplies[reportedType])
|
|
supplies[reportedType] = [];
|
|
|
|
supplies[reportedType].push({
|
|
"entity": ent,
|
|
"amount": amount,
|
|
"type": type,
|
|
"position": ent.position(),
|
|
});
|
|
});
|
|
return supplies;
|
|
},
|
|
});
|