L'application est à la racine du site : plateau en SVG, saisie au toucher (pion puis case d'arrivée, proposées à partir du moteur), boutons du jet, du videau et de nouvelle partie, coup de l'ordinateur affiché avec son temps, fin de partie, reprise depuis localStorage, aide lue dans les copies de docs/. Le moteur tourne dans le Web Worker existant ; main.ts est le seul assembleur (nouvelles règles dependency-cruiser). Le service worker met tout le site en cache, avec une empreinte du contenu comme version. Les pages de test du moteur passent sous /moteur/. Politique de sécurité du contenu dans le Caddyfile ; make test-browser joue une partie dans Chromium et Firefox sans écran (Playwright, hors de make test). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.5 KiB
JavaScript
67 lines
2.5 KiB
JavaScript
// engine-client.mjs -- le moteur vu depuis les pages de test : démarre le
|
|
// Web Worker (../engine-worker.mjs, partagé avec l'application) et lui envoie
|
|
// les commandes.
|
|
//
|
|
// Copyright (C) 2026 les auteurs d'Ustagammon.
|
|
// Licence : GPLv3 ou ultérieure (voir LICENSE).
|
|
//
|
|
// Toutes les fonctions renvoient une promesse de { result, ms, memoryBytes } :
|
|
// result est l'objet JSON d'engine-cli, ms le temps de calcul mesuré dans le
|
|
// Worker. La promesse est rejetée si le moteur signale une erreur.
|
|
|
|
import { commands } from "../engine-wasm.mjs";
|
|
|
|
export function startEngine() {
|
|
const worker = new Worker(new URL("../engine-worker.mjs", import.meta.url), { type: "module" });
|
|
const pending = new Map();
|
|
let nextId = 1;
|
|
let resolveReady, rejectReady;
|
|
const ready = new Promise((resolve, reject) => {
|
|
resolveReady = resolve;
|
|
rejectReady = reject;
|
|
});
|
|
|
|
worker.onmessage = (event) => {
|
|
const message = event.data;
|
|
if (message.type === "ready") {
|
|
resolveReady(message);
|
|
} else if (message.type === "failed") {
|
|
rejectReady(new Error(message.message));
|
|
} else {
|
|
const { resolve, reject } = pending.get(message.id);
|
|
pending.delete(message.id);
|
|
if (message.error) {
|
|
reject(new Error(message.error));
|
|
} else {
|
|
resolve(message);
|
|
}
|
|
}
|
|
};
|
|
// Erreur au chargement du Worker lui-même (fichier absent, navigateur
|
|
// trop ancien pour les Workers en module ES…).
|
|
worker.onerror = (event) => {
|
|
rejectReady(new Error(event.message || "le Web Worker du moteur n'a pas démarré"));
|
|
};
|
|
|
|
function run(args) {
|
|
const id = nextId++;
|
|
return new Promise((resolve, reject) => {
|
|
pending.set(id, { resolve, reject });
|
|
worker.postMessage({ id, args: args.map(String) });
|
|
});
|
|
}
|
|
|
|
return {
|
|
// Promesse de { loadMs, memoryBytes } une fois le moteur chargé.
|
|
ready,
|
|
bestMove: (positionId, matchId, dice, ply) =>
|
|
run(commands.bestMove(positionId, matchId, dice, ply)),
|
|
cubeDecision: (positionId, matchId, ply) =>
|
|
run(commands.cubeDecision(positionId, matchId, ply)),
|
|
evaluate: (positionId, matchId, ply) =>
|
|
run(commands.evaluate(positionId, matchId, ply)),
|
|
reference: (positionId, matchId, dice, ply) =>
|
|
run(commands.reference(positionId, matchId, dice, ply)),
|
|
};
|
|
}
|