This was SVN commit r9379.

This commit is contained in:
James Baillie 2011-05-01 15:03:51 +00:00
parent 02ed11ac54
commit 126c2276cd

View File

@ -1,146 +0,0 @@
/*
* This is a primitive initial attempt at an AI player.
* The design isn't great and maybe the whole thing should be rewritten -
* the aim here is just to have something that basically works, and to
* learn more about what's really needed for a decent AI design.
*
* The basic idea is we have a collection of independent modules
* (EconomyManager, etc) which produce a list of plans.
* The modules are mostly stateless - each turn they look at the current
* world state, and produce some plans that will improve the state.
* E.g. if there's too few worker units, they'll do a plan to train
* another one. Plans are discarded after the current turn, if they
* haven't been executed.
*
* Plans are grouped into a small number of PlanGroups, and for each
* group we try to execute the highest-priority plans.
* If some plan groups need more resources to execute their highest-priority
* plan, we'll distribute any unallocated resources to that group's
* escrow account. Eventually they'll accumulate enough to afford their plan.
* (The purpose is to ensure resources are shared fairly between all the
* plan groups - none of them should be starved even if they're trying to
* execute a really expensive plan.)
*/
/*
* Lots of things we should fix:
*
* * Find entities with no assigned role, and give them something to do
* * Keep some units back for defence
* * Consistent terminology (type vs template etc)
* * ...
*
*/
function TestBotAI(settings)
{
// warn("Constructing TestBotAI for player "+settings.player);
BaseAI.call(this, settings);
this.turn = 0;
this.modules = [
new EconomyManager(),
new MilitaryAttackManager(),
];
this.planGroups = {
economyPersonnel: new PlanGroup(),
economyConstruction: new PlanGroup(),
militaryPersonnel: new PlanGroup(),
};
}
TestBotAI.prototype = new BaseAI();
TestBotAI.prototype.ShareResources = function(remainingResources, unaffordablePlans)
{
// Share our remaining resources among the plangroups that need
// to accumulate more resources, in proportion to their priorities
for each (var type in remainingResources.types)
{
// Skip resource types where we don't have any spare
if (remainingResources[type] <= 0)
continue;
// Find the plans that require some of this resource type,
// and the sum of their priorities
var ps = [];
var sumPriority = 0;
for each (var p in unaffordablePlans)
{
if (p.plan.getCost()[type] > p.group.getEscrow()[type])
{
ps.push(p);
sumPriority += p.priority;
}
}
// Avoid divisions-by-zero
if (!sumPriority)
continue;
// Share resources by priority, clamped to the amount the plan actually needs
for each (var p in ps)
{
var amount = Math.floor(remainingResources[type] * p.priority / sumPriority);
var max = p.plan.getCost()[type] - p.group.getEscrow()[type];
p.group.getEscrow()[type] += Math.min(max, amount);
}
}
};
TestBotAI.prototype.OnUpdate = function()
{
// Run the update every n turns, offset depending on player ID to balance the load
if ((this.turn + this.player) % 4 == 0)
{
var gameState = new GameState(this);
// Find the resources we have this turn that haven't already
// been allocated to an escrow account.
// (We need to do this before executing any plans, because those will
// distort the escrow figures.)
var remainingResources = gameState.getResources();
for each (var planGroup in this.planGroups)
remainingResources.subtract(planGroup.getEscrow());
Engine.ProfileStart("plan setup");
// Compute plans from each module
for each (var module in this.modules)
module.update(gameState, this.planGroups);
// print(uneval(this.planGroups)+"\n");
Engine.ProfileStop();
Engine.ProfileStart("plan execute");
// Execute as many plans as possible, and keep a record of
// which ones we can't afford yet
var unaffordablePlans = [];
for each (var planGroup in this.planGroups)
{
var plan = planGroup.executePlans(gameState);
if (plan)
unaffordablePlans.push({"group": planGroup, "priority": plan.priority, "plan": plan.plan});
}
Engine.ProfileStop();
this.ShareResources(remainingResources, unaffordablePlans);
// print(uneval(this.planGroups)+"\n");
// Reset the temporary plan data
for each (var planGroup in this.planGroups)
planGroup.resetPlans();
}
if (this.turn == 0){
this.chat("Good morning. Please prepare for annihilation. Jubal apologises for any inconvenience likely to be caused by your imminent demise.");
}
this.turn++;
};