mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
The functions were defined on the `Headquarters` prototype. But not all functions are needed outside of "startingStrategy.js". Also doing it this way, "startingStrategy.js" and "headquarters.js" had to mutually import each other.
176 lines
4.7 KiB
JavaScript
176 lines
4.7 KiB
JavaScript
import { BaseAI } from "simulation/ai/common-api/baseAI.js";
|
|
import { Entity } from "simulation/ai/common-api/entity.js";
|
|
import { Config } from "simulation/ai/petra/config.js";
|
|
import { Headquarters } from "simulation/ai/petra/headquarters.js";
|
|
import { Queue } from "simulation/ai/petra/queue.js";
|
|
import { QueueManager } from "simulation/ai/petra/queueManager.js";
|
|
import { gameAnalysis } from "simulation/ai/petra/startingStrategy.js";
|
|
|
|
export function PetraBot(settings)
|
|
{
|
|
BaseAI.call(this, settings);
|
|
|
|
// played turn, because Petra doesn't play every turn.
|
|
this.turn = 0;
|
|
this.playedTurn = 0;
|
|
this.elapsedTime = 0;
|
|
|
|
this.uniqueIDs = {
|
|
"armies": 1, // starts at 1 to allow easier tests on armies ID existence
|
|
"bases": 1, // base manager ID starts at one because "0" means "no base" on the map
|
|
"plans": 0, // training/building/research plans
|
|
"transports": 1 // transport plans start at 1 because 0 might be used as none
|
|
};
|
|
|
|
this.Config = new Config(settings.difficulty, settings.behavior);
|
|
|
|
this.savedEvents = {};
|
|
}
|
|
|
|
PetraBot.prototype = Object.create(BaseAI.prototype);
|
|
|
|
PetraBot.prototype.CustomInit = function(gameState)
|
|
{
|
|
if (this.isDeserialized)
|
|
{
|
|
// WARNING: the deserializations should not modify the metadatas infos inside their init functions
|
|
this.canPlay = this.data.canPlay;
|
|
this.turn = this.data.turn;
|
|
this.playedTurn = this.data.playedTurn;
|
|
this.elapsedTime = this.data.elapsedTime;
|
|
this.savedEvents = this.data.savedEvents;
|
|
for (const key in this.savedEvents)
|
|
{
|
|
for (const i in this.savedEvents[key])
|
|
{
|
|
const evt = this.savedEvents[key][i];
|
|
const evtmod = {};
|
|
for (const keyevt in evt)
|
|
{
|
|
evtmod[keyevt] = evt[keyevt];
|
|
this.savedEvents[key][i] = evtmod;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.Config.Deserialize(this.data.config);
|
|
|
|
this.queueManager = new QueueManager(this.Config, {});
|
|
this.queueManager.Deserialize(gameState, this.data.queueManager);
|
|
this.queues = this.queueManager.queues;
|
|
|
|
this.HQ = new Headquarters(this.Config, true);
|
|
this.HQ.init(gameState, this.queues);
|
|
this.HQ.Deserialize(gameState, this.data.HQ);
|
|
|
|
this.uniqueIDs = this.data.uniqueIDs;
|
|
this.isDeserialized = false;
|
|
this.data = undefined;
|
|
|
|
// initialisation needed after the completion of the deserialization
|
|
this.HQ.postinit(gameState);
|
|
}
|
|
else
|
|
{
|
|
this.Config.setConfig(gameState);
|
|
|
|
// this.queues can only be modified by the queue manager or things will go awry.
|
|
this.queues = {};
|
|
for (const i in this.Config.priorities)
|
|
this.queues[i] = new Queue();
|
|
|
|
this.queueManager = new QueueManager(this.Config, this.queues);
|
|
|
|
this.HQ = new Headquarters(this.Config, false);
|
|
|
|
this.HQ.init(gameState, this.queues);
|
|
|
|
// Try to analyze our starting position and set a strategy.
|
|
this.canPlay = gameAnalysis(this.HQ, gameState);
|
|
}
|
|
};
|
|
|
|
PetraBot.prototype.OnUpdate = function(sharedScript)
|
|
{
|
|
if (this.isDeserialized)
|
|
this.Init(PlayerID, sharedScript);
|
|
|
|
if (this.gameFinished || this.gameState.playerData.state == "defeated")
|
|
return;
|
|
|
|
for (const i in sharedScript.events)
|
|
{
|
|
if (i == "AIMetadata") // not used inside petra
|
|
continue;
|
|
if (this.savedEvents[i] !== undefined)
|
|
this.savedEvents[i] = this.savedEvents[i].concat(sharedScript.events[i]);
|
|
else
|
|
this.savedEvents[i] = sharedScript.events[i];
|
|
}
|
|
|
|
// Run the update every n turns, offset depending on player ID to balance the load
|
|
this.elapsedTime = this.gameState.getTimeElapsed() / 1000;
|
|
if (!this.playedTurn || (this.turn + this.player) % 8 == 5)
|
|
{
|
|
Engine.ProfileStart("PetraBot bot (player " + this.player +")");
|
|
|
|
this.playedTurn++;
|
|
|
|
if (!this.canPlay)
|
|
{
|
|
Engine.ProfileStop();
|
|
return;
|
|
}
|
|
|
|
this.HQ.update(this.gameState, this.queues, this.savedEvents);
|
|
|
|
this.queueManager.update(this.gameState);
|
|
|
|
for (const i in this.savedEvents)
|
|
this.savedEvents[i] = [];
|
|
|
|
Engine.ProfileStop();
|
|
}
|
|
|
|
this.turn++;
|
|
};
|
|
|
|
PetraBot.prototype.Serialize = function()
|
|
{
|
|
if (this.isDeserialized)
|
|
return this.data;
|
|
|
|
const savedEvents = {};
|
|
for (const key in this.savedEvents)
|
|
{
|
|
savedEvents[key] = this.savedEvents[key].slice();
|
|
for (const i in savedEvents[key])
|
|
{
|
|
if (!savedEvents[key][i])
|
|
continue;
|
|
const evt = savedEvents[key][i];
|
|
const evtmod = {};
|
|
for (const keyevt in evt)
|
|
evtmod[keyevt] = evt[keyevt];
|
|
savedEvents[key][i] = evtmod;
|
|
}
|
|
}
|
|
|
|
return {
|
|
"canPlay": this.canPlay,
|
|
"uniqueIDs": this.uniqueIDs,
|
|
"turn": this.turn,
|
|
"playedTurn": this.playedTurn,
|
|
"elapsedTime": this.elapsedTime,
|
|
"savedEvents": savedEvents,
|
|
"config": this.Config.Serialize(),
|
|
"queueManager": this.queueManager.Serialize(),
|
|
"HQ": this.HQ.Serialize()
|
|
};
|
|
};
|
|
|
|
PetraBot.prototype.Deserialize = function(data, sharedScript)
|
|
{
|
|
this.isDeserialized = true;
|
|
this.data = data;
|
|
};
|