module TK.SpaceTac { /** * Initialize the background worker, if possible */ function initializeWorker(): Worker | null { if (typeof window != "undefined" && (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 { 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 { 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 { let serializer = new Serializer(TK.SpaceTac); let promise: Promise = 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 { 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; } } }