Files
Ustagammon/docs/plans/2026-11-03-coup-adverse.md
T
2026-11-03 02:00:58 +01:00

7.9 KiB

Montrer le coup que l'ordinateur vient de jouer

  • Date : 2026-11-03
  • Étape : 0d (retour de Pierre sur le plateau publié)
  • Statut : terminé
  • Exécutant : sous-agent general-purpose, dans un worktree isolé

Objectif

Après le coup de l'ordinateur, le joueur voit ce qui a bougé sans lire la notation. Choix de Pierre : animation puis traces.

Consignes

  1. Animation : quand l'ordinateur joue, ses pions glissent un par un, un demi-coup après l'autre (environ 0,4 s chacun), de la case de départ à la case d'arrivée. Un pion frappé part sur la barre de façon visible. Si le système demande moins d'animations (prefers-reduced-motion), pas d'animation : on passe directement aux traces.
  2. Traces : une fois l'animation finie, et jusqu'à la prochaine action du joueur (lancer les dés, doubler, prendre, passer, toucher un pion) :
    • une flèche de chaque case de départ vers sa case d'arrivée ;
    • les pions déplacés entourés ;
    • à la case de départ d'un pion parti, un pion « fantôme » (contour seul) ;
    • un pion frappé signalé sur la barre. Les petits points orange actuels sont remplacés par ces traces.
  3. Bouton « Revoir » à côté des boutons d'action : il rejoue l'animation du dernier coup de l'ordinateur, puis remet les traces. Il disparaît dès que le joueur agit.
  4. Où vit la logique : la liste des demi-coups du dernier coup de l'ordinateur et les positions intermédiaires viennent du domaine (le journal contient déjà MovePlayed avec ses demi-coups ; ajouter si besoin une fonction qui donne la suite des plateaux intermédiaires, à partir du moteur, sans réimplémenter de règle : par exemple checkHalfMoves ou le décodage de position à chaque étape). L'interface ne fait que dessiner. Les garde-fous d'architecture existants doivent passer.
  5. Textes dans app/src/ui/texts.ts ; mots du glossaire.
  6. Scénario (ADR 0008) : ajouter à docs/scenarios/jouer-une-partie.feature un scénario « Voir le coup de l'ordinateur », écrit en intentions (par exemple : quand l'ordinateur a joué, alors son coup vous est montré case par case, et vous pouvez le revoir), avec ses étapes Cucumber sur le domaine.
  7. Tests :
    • tests unitaires de ce qui est calculable hors navigateur (traces et plateaux intermédiaires d'un coup avec et sans pion frappé, coup depuis la barre, sortie de pions) ;
    • make test-browser (tests/browser/play.mjs) : après un coup de l'ordinateur, les flèches et les pions entourés sont présents ; « Revoir » rejoue puis les remet ; tout disparaît à l'action suivante ; capture d'écran coup-adverse ;
    • make lint, make test et make test-browser verts.

Contraintes :

  • CLAUDE.md, ADR 0007, 0008, 0009 : simplicité, pas de framework ni de bibliothèque d'animation (animations CSS ou requestAnimationFrame), identifiants en anglais, commentaires et textes en français ;
  • aucune règle du jeu réimplémentée ;
  • l'animation ne doit pas retarder le moteur ni bloquer la saisie au-delà de sa durée ; le temps de calcul affiché reste celui du moteur ;
  • ne pas publier, ne pas pousser, ne pas créer de merge request ;
  • commits petits, en français, avec la ligne Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>.

Rapport attendu : ce qui a été fait, captures d'écran (chemins), résultat des tests, difficultés, écarts au plan.

Critères de réussite

  • Dans Chromium et Firefox sans interface, après chaque coup de l'ordinateur : animation (ou traces directes en mouvement réduit), traces visibles, « Revoir » fonctionnel, traces effacées à l'action suivante.
  • Le scénario « Voir le coup de l'ordinateur » passe dans make test.
  • make lint, make test et make test-browser passent.

Résultat

Terminé le 2026-11-03, branche coup-adverse-travail.

Domaine (app/src/domain/game/game.ts) : Game.lastMoveSteps() donne le dernier coup joué demi-coup par demi-coup (MoveSteps : camp, demi-coups, plateaux successifs, pions frappés). Les plateaux intermédiaires viennent du moteur : checkHalfMoves sur les premiers demi-coups depuis la position d'avant le coup, puis board. Un pion frappé se lit sur le plateau du moteur (la barre adverse grossit), aucune règle n'est rejouée. Le format des événements ne change pas.

Interface :

  • board-model.ts : moveTrace() calcule les traces (une flèche par demi-coup, pions arrivés, pions partis, pions frappés). Un pion qui fait étape (13/7 7/4) ne laisse rien sur la case d'étape. Testé sous Node.
  • board-view.ts : traces dessinées en laiton (--last-move, comme le demande la charte) : flèches avec pointe, pions arrivés entourés, pion fantôme en pointillés à la case de départ, pion frappé entouré en pointillés sur la barre. Les petits points orange ont disparu. La géométrie des piles est regroupée dans slotCenter(). Le pion du dessus de chaque endroit porte data-checker. slideChecker() le fait glisser avec Element.animate (API du navigateur, sans bibliothèque).
  • app.ts : après le tour de l'ordinateur, le plateau est redessiné à chaque étape et le pion arrivé glisse en 0,4 s depuis sa case de départ. Un pion frappé glisse en même temps vers la barre. Ensuite viennent les traces et le bouton « Revoir ». Tout s'efface à l'action suivante (lancer, doubler, prendre, passer, nouvelle partie, toucher un pion). Avec prefers-reduced-motion: reduce, les traces s'affichent directement. L'animation commence une fois le moteur fini : le temps affiché reste celui du moteur. Les touches sont ignorées pendant l'animation (au plus 0,4 s par demi-coup). Une partie reprise juste après le coup de l'ordinateur montre ses traces sans l'animer.
  • Textes replay et replayTitle dans texts.ts, bouton #replay dans web/index.html.

Scénario « Voir le coup de l'ordinateur » dans docs/scenarios/jouer-une-partie.feature. Il part d'une position où le seul coup permis de l'ordinateur avec 3-1 frappe votre blot (13/10* 10/9), avec le videau chez vous pour qu'il ne double pas. Ses étapes vérifient les plateaux case par case, le pion frappé qui part sur la barre et un second appel identique (« revoir »).

Tests :

  • app/tests/move-steps.test.ts (vrai moteur) : coup simple, pion frappé, coup depuis la barre qui frappe en rentrant, sortie jusqu'à la fin de partie, coup de l'ordinateur, aucun coup.
  • app/tests/ui.test.ts : traces d'un coup simple, d'un pion qui fait étape, d'une rentrée avec un pion frappé, d'une sortie.
  • tests/browser/play.mjs : après chaque action, les traces sont là si le dernier coup est celui de l'ordinateur (autant de flèches que de demi-coups, au moins un pion entouré et un fantôme, « Revoir » visible), et absentes sinon. « Revoir » est essayé deux fois. La première fois, des animations tournent et les flèches disparaissent pendant l'animation, puis les mêmes traces reviennent ; une capture coup-adverse est prise. La seconde fois, en mouvement réduit, aucune animation ne tourne et les traces reviennent.
  • Résultats : make lint sans problème ; make test 10/10 ; make test-browser vert sous Chromium (coup de l'ordinateur montré 26 fois) et Firefox (43 fois), sans violation CSP ni erreur dans la page.

Limites :

  • Aucune des deux parties du navigateur n'a vu l'ordinateur frapper (0 pion frappé signalé). L'animation vers la barre n'est donc vérifiée que par le scénario et les tests unitaires (plateaux et traces), pas dans un navigateur.
  • Firefox a affiché un tour de l'ordinateur à 4,4 s au plus. Ce temps est mesuré avant l'animation, qui n'y est pour rien : c'est le moteur sous Firefox sur le PC de 2011. Chromium : 0,6 s au plus.
  • Sur une case de plus de cinq pions, c'est le cinquième pion dessiné qui glisse (le nombre reste affiché sur la pile).