6.4 KiB
Comparer le moteur embarqué aux références de gnubg de bureau
- Date : 2026-11-02
- Étape : 0a.4
- Statut : terminé
- Exécutant : sous-agent general-purpose, dans un worktree isolé
Objectif
make test vérifie automatiquement que le moteur embarqué (build/engine-cli)
retrouve les résultats de gnubg de bureau sur les 32 positions de
tests/reference/, aux niveaux 0 et 2 plis, avec une tolérance mesurée et
justifiée.
Consignes
- Sortie d'
engine-clialignée sur le contrat detests/reference/README.md: une sous-commande (par exempleengine-cli reference <position_id> <match_id> [dés], ou une option) produit, pour une position et un niveau, un objet de même structure que la partieplies["<n>"]d'un fichier de résultat (evaluation,movesoucube). Le classement des coups suit exactement la méthode de la commandehintde gnubg (documentée dans le README du format) : nombre de coups, notation, pli réel de chaque coup. Garderengine-clisimple : réutiliser les fonctions d'engine.h, compléterengine.hsi nécessaire. - Comparateur : un script lisible (Python 3 ou shell avec
jq) qui, pour chaque position et chaque niveau, appelleengine-cli, compare au résultat de référence et affiche un rapport clair (position, niveau, champ, valeur attendue, valeur obtenue, écart). Il tourne dans Docker (ajouter ce qu'il faut àdocker/build-c/Dockerfileet changer l'étiquette de l'image dans leMakefile), jamais avec les outils du PC (ADR 0004). - Critères de concordance :
- même nombre de coups légaux ;
- même meilleur coup, sauf si gnubg lui-même sépare les deux premiers coups de moins que la tolérance (cas d'égalité : le dire dans le rapport) ;
- même pli réel du meilleur coup ;
- équités et probabilités à la tolérance près, pour les coups communs ;
- même décision de videau, et équités du videau à la tolérance près.
- Tolérance mesurée, pas devinée : mesurer l'écart maximal observé sur
les 32 positions, l'expliquer (gnubg de bureau en SSE2 avec
-ffast-math, moteur embarqué en C générique), et mesurer aussi l'écart d'un build du moteur sans-ffast-math. Fixer la tolérance avec une marge raisonnable et la justifier danstests/reference/README.md. tests/test_engine_reference.sh, lancé parmake test: lancemake enginesi nécessaire puis le comparateur ; échoue avec le rapport si un critère n'est pas tenu.tests/test_reference.shn'utilise plusjqsur le PC : passer par l'image Docker de la chaîne C (ADR 0004), et mettreCREDITS.mdà jour.
Contraintes :
- respecter
CLAUDE.mdet les ADR 0004, 0005 et 0007 : simplicité, identifiants en anglais, commentaires en français, aucune installation hors Docker,-j2; - ne pas modifier les références (
tests/reference/results/) ni les fichiers deengine/gnubg/; si une divergence vient d'un vrai défaut du moteur embarqué, corriger dansengine/compat/ouengine/src, et le dire ; - ne rien masquer : si une position ne concorde pas, le rapport doit le montrer, avec la cause trouvée ou les hypothèses ;
make lintetmake testdoivent passer ; commits petits, en français, avec la ligneCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>;- ne pas pousser ni créer de merge request.
Rapport attendu : ce qui a été fait, la tolérance retenue et sa justification
(écarts mesurés avec et sans -ffast-math), les éventuelles divergences et
leur cause, les commandes de vérification.
Critères de réussite
make testcompare les 32 positions aux deux niveaux et passe.- La tolérance est documentée et justifiée par des mesures.
- Une divergence volontairement introduite (par exemple une référence modifiée dans une copie) fait échouer le test avec un rapport lisible.
Résultat
Terminé le 2026-11-02, branche comparaison-travail. make lint et
make test passent (7/7) ; les 32 positions concordent aux deux niveaux
avec la tolérance retenue, sans aucune égalité de meilleur coup à signaler.
Fait.
engine-cli --ply N reference POSITION_ID MATCH_ID [DÉS]produit un niveau au format detests/reference/(evaluation, puismovesoucube). Nombres écrits avec 9 chiffres significatifs (float32 exact).tests/reference/compare.py(Python 3) ettests/test_engine_reference.sh(lancé parmake test) : comparaison dans l'imageustagammon/build-c:2, qui reçoit Python 3 et jq.tests/test_reference.shse relance dans cette image : plus de jq sur le PC.CREDITS.mdà jour.- Critères, tolérance et mesures documentés dans
tests/reference/README.md.
Défauts du moteur embarqué trouvés et corrigés (engine/engine.c) :
- en match, l'équité des coups classés était convertie deux fois par
mwc2eq(ScoreMovela convertit déjà) ; engine_best_movesn'appliquait pas touthint:fAnalyseétait faux etRefreshMoveListabsent (classement par niveau d'évaluation, puis départage des égalités).
Changements d'interface : engine_cube gagne optimal et decision_text ;
decision prend le nom de l'énumération de gnubg (DOUBLE_TAKE…), comme
les références (tests/test_engine.sh adapté).
Tolérance : 0,002, sur probabilités et équités. Mesures sur 2 598
nombres : écart maximal 9,5e-4 et 99 % des écarts sous 1,6e-4, que le moteur
soit compilé avec ou sans -ffast-math (les deux builds diffèrent entre eux
de 1,1e-6 au plus). La cause est la sigmoïde de gnubg de bureau en SSE2 avec
-ffast-math, qui calcule 1/x par _mm_rcp_ps (environ 12 bits) ; preuve :
le moteur compilé en SSE2 pour l'essai redonne les références au bit près.
L'écart maximal vient d'un seul coup (opening-64-match, 2 plis, 8/2 6/2),
où l'écart de 1e-4 fait basculer un choix discret de la recherche.
Critère de divergence vérifié : sur une copie de results/ avec une
équité décalée de 0,01, un nombre de coups légaux, une décision de videau et
un meilleur coup modifiés, compare.py --results <copie> échoue avec un
tableau de 10 écarts lisibles.
Suites possibles : mesurer de même sur téléphone (NEON, autre
approximation de la division) ; envisager un build SSE2 d'engine-cli sur PC
si l'on veut une concordance au bit près (non retenu : le moteur de
l'application tournera en C générique ou en NEON).