Moteur en WebAssembly : make engine-wasm et suite de contrat
Le moteur et engine-cli sont compilés avec Emscripten (image figée emscripten/emsdk:3.1.64), en C générique, sans threads ; les données de build/data/ sont incluses dans engine.data. Le JavaScript appelle engine_init une fois puis main pour chaque commande : la sortie est le JSON d'engine-cli, sans code de mise en forme dupliqué. tests/test_wasm_reference.sh rejoue les 32 positions de référence sous Node avec le même comparateur (option --cli) et la même tolérance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
850de27e90
commit
b0030521d8
@@ -0,0 +1,78 @@
|
||||
// engine-wasm.mjs -- le moteur WebAssembly vu depuis JavaScript.
|
||||
//
|
||||
// Copyright (C) 2026 les auteurs d'Ustagammon.
|
||||
// Licence : GPLv3 ou ultérieure (voir LICENSE).
|
||||
//
|
||||
// Le WebAssembly (build/wasm/, voir engine-wasm/wasm.mk) contient le moteur
|
||||
// et le programme engine-cli. On charge le module une fois, on initialise le
|
||||
// moteur, puis chaque commande est un appel à main avec les mêmes arguments
|
||||
// qu'engine-cli en ligne de commande : la sortie est donc le même JSON.
|
||||
//
|
||||
// Utilisé par le Web Worker de la page (engine-worker.mjs) et, sous Node,
|
||||
// par engine-wasm/engine-cli.mjs et engine-wasm/bench.mjs. Le moteur calcule
|
||||
// sur le fil qui l'appelle : dans le navigateur, toujours dans un Worker.
|
||||
|
||||
// Dossier des données dans le système de fichiers virtuel (--preload-file).
|
||||
const DATA_DIR = "/data";
|
||||
|
||||
// createEngineModule : la fonction exportée par build/wasm/engine.mjs.
|
||||
// wasmDir : où trouver engine.wasm et engine.data, terminé par « / » (une
|
||||
// adresse dans le navigateur, un chemin de fichier sous Node).
|
||||
// Renvoie le moteur prêt, avec :
|
||||
// - runText(args) : { text, exitCode }, la sortie brute d'engine-cli ;
|
||||
// - run(args) : { result, ms }, le JSON décodé et le temps de calcul
|
||||
// (lève une erreur si le moteur en signale une) ;
|
||||
// - memoryBytes() : taille actuelle de la mémoire WebAssembly.
|
||||
export async function loadEngine(createEngineModule, wasmDir) {
|
||||
let output = [];
|
||||
const module = await createEngineModule({
|
||||
locateFile: (name) => wasmDir + name,
|
||||
print: (line) => output.push(line),
|
||||
printErr: (line) => output.push(line),
|
||||
});
|
||||
|
||||
const status = module.ccall("engine_init", "number", ["string"], [DATA_DIR]);
|
||||
if (status !== 0) {
|
||||
throw new Error("le moteur n'a pas pu charger ses données (code " + status + ")");
|
||||
}
|
||||
|
||||
function runText(args) {
|
||||
output = [];
|
||||
const exitCode = module.callMain(args.map(String));
|
||||
return { text: output.join("\n"), exitCode };
|
||||
}
|
||||
|
||||
function run(args) {
|
||||
const start = performance.now();
|
||||
const { text } = runText(args);
|
||||
const ms = performance.now() - start;
|
||||
const result = JSON.parse(text);
|
||||
if (result.error) {
|
||||
throw new Error(result.error.message);
|
||||
}
|
||||
return { result, ms };
|
||||
}
|
||||
|
||||
return {
|
||||
runText,
|
||||
run,
|
||||
memoryBytes: () => module.HEAPU8.length,
|
||||
};
|
||||
}
|
||||
|
||||
// Arguments d'engine-cli pour chaque fonction de l'interface. Les dés sont
|
||||
// un tableau [3, 1] ou une chaîne « 31 ».
|
||||
export const commands = {
|
||||
bestMove: (positionId, matchId, dice, ply) =>
|
||||
["--ply", ply, "bestmove", positionId, matchId, diceText(dice)],
|
||||
cubeDecision: (positionId, matchId, ply) =>
|
||||
["--ply", ply, "cube", positionId, matchId],
|
||||
evaluate: (positionId, matchId, ply) =>
|
||||
["--ply", ply, "eval", positionId, matchId],
|
||||
reference: (positionId, matchId, dice, ply) =>
|
||||
["--ply", ply, "reference", positionId, matchId, ...(dice ? [diceText(dice)] : [])],
|
||||
};
|
||||
|
||||
function diceText(dice) {
|
||||
return Array.isArray(dice) ? dice.join("") : String(dice);
|
||||
}
|
||||
Reference in New Issue
Block a user