1
0
Fork 0
spacetac/src/core/ai/AIWorker.ts

85 lines
2.8 KiB
TypeScript

module TK.SpaceTac {
/**
* Initialize the background worker, if possible
*/
function initializeWorker(): Worker | null {
if (typeof window != "undefined" && (<any>window).Worker) {
try {
return new Worker('aiworker.js'); // TODO not hard-coded
} catch {
console.error("Could not initialize AI web worker");
return null;
}
} else {
return null;
}
}
/**
* AI processing, either in the current process or in a web worker
*/
export class AIWorker {
private static worker = initializeWorker();
constructor(private battle: Battle, private player = battle.fleets[1].player, private debug = false) {
}
/**
* Process the current playing ship with an AI
*
* This should be done on the real battle state
*/
static process(battle: Battle, player?: Player, debug = false): Promise<TurnPlan> {
const processing = new AIWorker(battle, player, debug);
return processing.processAuto();
}
/**
* Process AI in a webworker if possible, else do the work in the render thread
*/
processAuto(): Promise<TurnPlan> {
if (!this.debug && AIWorker.worker) {
try {
return this.processInWorker(AIWorker.worker);
} catch (err) {
console.error("Web worker error, falling back to main thread", err);
return this.processHere();
}
} else {
return this.processHere();
}
}
/**
* Process AI in a webworker
*/
processInWorker(worker: Worker): Promise<TurnPlan> {
let serializer = new Serializer(TK.SpaceTac);
let promise: Promise<TurnPlan> = new Promise((resolve, reject) => {
worker.onerror = reject;
worker.onmessage = (message) => {
let plan = serializer.unserialize(message.data);
if (this.debug) {
console.log("Received from AI worker", plan);
}
// TODO check type
resolve(plan);
};
});
worker.postMessage(serializer.serialize(this));
return promise;
}
/**
* Process AI in current thread
*/
async processHere(): Promise<TurnPlan> {
const settings = AISettingsStock.default(this.battle, this.player); // TODO settings choice ?
let ai = new ContinuousAI(settings, this.debug);
ai.play();
const result = await ai.getPlan(); // TODO Only when human player is done
return result.plan;
}
}
}