From a556c67fef8337d79b7e12d40bd991af86d941b1 Mon Sep 17 00:00:00 2001 From: Pierre MARTIN Date: Mon, 2 Nov 2026 20:45:00 +0100 Subject: [PATCH] =?UTF-8?q?Plan=20de=20l'=C3=A9tape=200d.1=20:=20r=C3=A9su?= =?UTF-8?q?ltat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- docs/plans/2026-11-02-domaine-partie.md | 77 ++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/docs/plans/2026-11-02-domaine-partie.md b/docs/plans/2026-11-02-domaine-partie.md index 3c6281c..6d84174 100644 --- a/docs/plans/2026-11-02-domaine-partie.md +++ b/docs/plans/2026-11-02-domaine-partie.md @@ -2,7 +2,7 @@ - **Date** : 2026-11-02 - **Étape** : 0d.1 -- **Statut** : en cours +- **Statut** : terminé (branche `plateau-domaine-travail`) - **Exécutant** : sous-agent general-purpose, dans un worktree isolé ## Objectif @@ -91,4 +91,77 @@ garde-fous, les difficultés, les écarts au plan. ## Résultat -À remplir à la clôture. +**Terminé.** `make lint` et `make test` passent (9/9, dont le nouveau +`tests/test_web.sh`). Les quatre critères de réussite sont tenus. + +**Moteur** (`engine.h`, `engine-cli`, tests natifs dans `tests/test_engine.sh`) : +- `engine_check_half_moves` / `halfmoves POSITION_ID DÉS "8/5 6/5"` : des + demi-coups saisis un par un sont-ils le début d'un coup légal, le forment-ils + en entier, et quelle position en résulte. La légalité de chaque demi-coup + vient de `GenerateMoves` de gnubg appelé avec un seul dé ; celle du coup + entier, de la liste des coups légaux (jouer le plus de dés possible). L'ordre + des demi-coups est libre (6/5 puis 8/5 est accepté) ; +- `engine_decode_position` / `position` : plateau (pions par case, barre, + sortis, compte de points), même position vue de l'adversaire, et + `engine_game_result` : partie finie, gagnant, simple/gammon/backgammon, + points (videau et règle Jacoby compris) ; +- `engine_encode_match` / `matchid VIDEAU PROPRIÉTAIRE` ; +- les coups (`legal`, `moves`, `bestmove`) donnent leurs demi-coups ; +- `cube` donne `available` (droit de doubler), `double` (décision + DOUBLE_TAKE, DOUBLE_PASS, DOUBLE_BEAVER, REDOUBLE_TAKE ou REDOUBLE_PASS) et + `take` (`double_take <= double_pass`). La sortie de `reference` est + inchangée : les suites de contrat natives et WebAssembly passent toujours. + +**Domaine** (`app/src/domain/game/`) : `Game.start(engine, { dice, ply, setup })`, +puis `roll()`, `playHalfMove({ from, to })` (false si refusé ; le coup est +enregistré dès qu'il est complet), `cancelHalfMoves()`, `double()`, `take()`, +`drop()`, `playComputerTurn()`, `undo()`, `goBackTo(id)` ; lecture par +`state` (phase, main, position vue de celui qui a la main, jet, videau, +résultat), `events`, `journal`, `displayedPosition`. Le journal est un arbre +d'événements gelés (`id`, `parent`, `version: 1`) ; `replay()` recalcule +l'état sans le moteur, chaque événement portant les positions calculées. +Niveau standard : 2 plis (`STANDARD_PLY`) ; sous Node sur le PC, une partie +entière à 2 plis prend 1,6 s, un tour de l'ordinateur quelques dizaines de ms. + +**Adaptateur** (`app/src/engine/wasm-engine.ts`) : `createWasmEngine(run)`, +où `run` exécute une commande d'engine-cli ; sous Node, +`app/tests/support/node-engine.ts` le branche sur `web/engine-wasm.mjs` et +`build/wasm/`. Dans le navigateur (0d.2), `run` passera par le Web Worker +existant (`web/engine-client.mjs`). + +**Scénarios** : les 7 scénarios de `jouer-une-partie.feature` passent (25 +étapes) sur le vrai moteur. Deux retouches : « vous essayez de jouer 8/4 » +avec 3-1 devient « 13/12 » (8/4 se joue légalement en 8/5/4 ; la case 12 est +tenue par l'ordinateur, expliqué dans le scénario) ; le constat « Et c'est +au tour de l'ordinateur » devient « Et c'est ensuite au tour de +l'ordinateur », Cucumber ne distinguant pas une situation de départ et un +constat de même texte. + +**Garde-fous** : dependency-cruiser (le domaine n'importe que le domaine, +l'interface n'importe pas le moteur, pas de cycle) ; `tests/test_web.sh` +génère des violations volontaires et vérifie que chacune est signalée. +`make lint` compile aussi le domaine seul sans types Node ni DOM. Vérifié à +la main : un import du moteur dans `side.ts` et une étape sans définition font +échouer `make test` ; un `code:` faux, une référence vers une fiche absente ou +un mauvais type font échouer `tests/test_glossary.sh`. + +**Glossaire** : fiches ajoutées Demi-coup (`HalfMove`) et Plateau (`Board`), +à relire ; `code:` ajouté à Coup (`Move`), Jet (`Roll`), Pli (`Ply`), Moteur +(`Engine`), Identifiant de position (`PositionId`), Videau (`Cube`), +Événement de partie (`GameEvent`), Partie (`Game`). + +**Écarts et limites** : +- `@cucumber/cucumber` 12.9.0 et non 13.x : la 13 exige Node 22.12 + (`require()` de modules ES) et l'image est en 22.11. Nouvelle dépendance de + types : `@types/node` (MIT), pour compiler les tests. +- Ce que le domaine fait lui-même, faute de place dans le moteur : alterner + les tours, le jet d'ouverture (le plus fort dé commence, égalité : on + relance), doubler la valeur du videau et le donner à celui qui prend, la + perte à la valeur d'avant le double quand on passe. +- Un demi-coup utilise un seul dé : 8/4 avec 3-1 se saisit 8/5 puis 5/4. +- Le coup est enregistré dès que les demi-coups forment un coup légal ; dans + le cas théorique où il pourrait encore être prolongé en un autre coup légal, + le joueur ne le pourrait pas. +- L'ordinateur ne double pas sur un double « facultatif » (OPTIONAL_*), ne + propose pas d'abandon, et les castors ne sont pas gérés. +- `app/src/ui/` ne contient qu'un `.gitkeep`.