Le moteur embarqué (MR !7) doit retrouver les résultats de GNU Backgammon de bureau (cadrage, ADR 0005), et c'est aux tests de le garantir, puisque le code n'est pas relu par un humain. C'est l'étape 0a.4 : make test compare automatiquement engine-cli aux 32 positions de référence produites par gnubg de bureau (MR !6), aux niveaux 0 et 2 plis, avec une tolérance mesurée et justifiée.
La comparaison a fait apparaître deux vrais défauts du moteur embarqué, que les tests de la MR !7 ne voyaient pas. Ils sont corrigés ici.
Cette MR consigne aussi la validation par Pierre des outils de compilation et de test de l'étape 0 (amendement de l'ADR 0004).
Quoi
Défauts corrigés dans engine/engine.c :
en match, l'équité des coups était convertie deux fois par mwc2eq ;
le classement des coups n'était pas exactement celui de la commande hint de gnubg. Il suit maintenant la même méthode : FindnSaveBestMoves avec fAnalyse, seuil arSkillLevel[SKILL_DOUBTFUL], puis RefreshMoveList.
engine-cli --ply N reference POSITION_ID MATCH_ID [DÉS] : produit un objet de même structure que plies["N"] d'un fichier de référence (le contrat de tests/reference/README.md). Les nombres sont écrits avec 9 chiffres significatifs, ce qui redonne exactement le float32.
engine.h : engine_cube gagne optimal et decision_text ; decision prend les noms de gnubg (DOUBLE_TAKE, NODOUBLE_TAKE…).
tests/reference/compare.py et tests/test_engine_reference.sh (lancé par make test). Les critères :
même nombre de coups légaux ;
même meilleur coup et même pli réel ;
équités et probabilités à la tolérance près ;
même décision de videau.
En cas d'écart, le rapport donne la position, le niveau, le champ, la valeur attendue, la valeur obtenue et l'écart.
Image ustagammon/build-c:2 : ajoute Python 3 et jq. tests/test_reference.sh s'y exécute, et jq n'est plus utilisé sur le PC (ADR 0004).
ADR 0004 amendé : table des outils validés par Pierre (ShellCheck, Node et @cucumber/gherkin, Debian et gnubg de référence, gcc, make, GLib, Python 3, jq, Emscripten), tous dans Docker et jamais embarqués.
Comment
Travail délégué à un sous-agent selon un plan écrit avant la délégation, supprimé à la clôture ; son résultat est repris ici.
Tolérance retenue : 0,002, mesurée sur 2 598 nombres :
Moteur comparé à gnubg de bureau
99 % des écarts sous
Écart maximal
C générique avec -ffast-math (build retenu)
1,6e-4
9,5e-4
C générique sans -ffast-math
1,6e-4
9,5e-4
Compilé en SSE2, pour l'essai
0
0 (identique au bit près)
L'écart vient du gnubg de bureau, pas de notre build. Compilé en SSE2 avec -ffast-math, gnubg calcule l'inverse dans sa sigmoïde avec _mm_rcp_ps, une instruction approchée (environ 12 bits), alors que le C générique fait une vraie division. La preuve : compilé en SSE2, notre moteur redonne les références au bit près.
Le seul écart au-delà de 1e-4 concerne opening-64-match à 2 plis (coup 8/2 6/2, 9,5e-4). L'hypothèse la plus probable, non vérifiée : une petite différence fait basculer un choix discret de la recherche à 2 plis.
La tolérance de 0,002 vaut environ deux fois l'écart maximal mesuré, et 15 fois moins que le seuil où gnubg qualifie un coup de « douteux » (0,03).
Vérification par la session principale, après fusion de main (MR !7) dans la branche :
make setup && make engine && make lint && make test : 7/7. La ligne de comparaison affiche « 32 positions, 64 niveaux, 2598 nombres comparés ; écart maximal 9.53e-04, tolérance 2e-03 » ;
références altérées dans une copie (équité décalée de 0,01, décision de videau changée) : le comparateur échoue et liste exactement les 2 écarts.
Choix et compromis
Le moteur reste en C générique, et non en SSE2, sur PC. Une concordance au bit près serait possible, mais l'application tournera en C générique (WebAssembly) ou en NEON (Android) : c'est ce chemin qu'il faut tester.
Une tolérance unique pour les probabilités et les équités : plus simple, et suffisante au regard des écarts mesurés.
Le format des nombres d'engine-cli passe à 9 chiffres significatifs pour toutes les commandes : un peu moins lisible, mais exact.
Risques et déploiement
make setup reconstruit l'image ustagammon/build-c (étiquette 2).
Changement d'interface dans engine.h (engine_cube) : aucun autre code ne l'utilise encore.
Sur téléphone, en NEON, gnubg utilise une autre approximation de la division. L'écart devra y être mesuré de la même façon si le socle Android est retenu.
Retour arrière : annuler le commit de fusion.
Comment vérifier
git switch main && git pull
make setup && make engine
make lint && make test
build/engine-cli --ply 2 reference 4HPwATDgc/ABMA cIkFAAAAAAAA 31
BUILD_C_IMAGE=ustagammon/build-c:2 bash tests/test_engine_reference.sh --details
Hors périmètre
La même suite de contrat sur le moteur WebAssembly : étape 0b, en cours.
Les MR de ce dépôt restent affichées « open » après fusion, à cause des hooks git du serveur Gitea (diagnostic à part) ; Pierre les marque fusionnées dans l'interface.
## Pourquoi
Le moteur embarqué (MR !7) doit retrouver les résultats de GNU Backgammon de bureau (cadrage, ADR 0005), et c'est aux tests de le garantir, puisque le code n'est pas relu par un humain. C'est l'étape 0a.4 : `make test` compare automatiquement `engine-cli` aux 32 positions de référence produites par gnubg de bureau (MR !6), aux niveaux 0 et 2 plis, avec une tolérance mesurée et justifiée.
La comparaison a fait apparaître **deux vrais défauts du moteur embarqué**, que les tests de la MR !7 ne voyaient pas. Ils sont corrigés ici.
Cette MR consigne aussi la validation par Pierre des outils de compilation et de test de l'étape 0 (amendement de l'ADR 0004).
## Quoi
- **Défauts corrigés dans `engine/engine.c`** :
- en match, l'équité des coups était convertie deux fois par `mwc2eq` ;
- le classement des coups n'était pas exactement celui de la commande `hint` de gnubg. Il suit maintenant la même méthode : `FindnSaveBestMoves` avec `fAnalyse`, seuil `arSkillLevel[SKILL_DOUBTFUL]`, puis `RefreshMoveList`.
- **`engine-cli --ply N reference POSITION_ID MATCH_ID [DÉS]`** : produit un objet de même structure que `plies["N"]` d'un fichier de référence (le contrat de `tests/reference/README.md`). Les nombres sont écrits avec 9 chiffres significatifs, ce qui redonne exactement le float32.
- **`engine.h`** : `engine_cube` gagne `optimal` et `decision_text` ; `decision` prend les noms de gnubg (`DOUBLE_TAKE`, `NODOUBLE_TAKE`…).
- **`tests/reference/compare.py`** et **`tests/test_engine_reference.sh`** (lancé par `make test`). Les critères :
- même nombre de coups légaux ;
- même meilleur coup et même pli réel ;
- équités et probabilités à la tolérance près ;
- même décision de videau.
En cas d'écart, le rapport donne la position, le niveau, le champ, la valeur attendue, la valeur obtenue et l'écart.
- **Image `ustagammon/build-c:2`** : ajoute Python 3 et jq. `tests/test_reference.sh` s'y exécute, et `jq` n'est plus utilisé sur le PC (ADR 0004).
- **ADR 0004 amendé** : table des outils validés par Pierre (ShellCheck, Node et `@cucumber/gherkin`, Debian et gnubg de référence, gcc, make, GLib, Python 3, jq, Emscripten), tous dans Docker et jamais embarqués.
## Comment
Travail délégué à un sous-agent selon un plan écrit avant la délégation, supprimé à la clôture ; son résultat est repris ici.
**Tolérance retenue : 0,002**, mesurée sur 2 598 nombres :
| Moteur comparé à gnubg de bureau | 99 % des écarts sous | Écart maximal |
| --- | --- | --- |
| C générique avec `-ffast-math` (build retenu) | 1,6e-4 | 9,5e-4 |
| C générique sans `-ffast-math` | 1,6e-4 | 9,5e-4 |
| Compilé en SSE2, pour l'essai | 0 | 0 (identique au bit près) |
**L'écart vient du gnubg de bureau, pas de notre build.** Compilé en SSE2 avec `-ffast-math`, gnubg calcule l'inverse dans sa sigmoïde avec `_mm_rcp_ps`, une instruction approchée (environ 12 bits), alors que le C générique fait une vraie division. La preuve : compilé en SSE2, notre moteur redonne les références au bit près.
Le seul écart au-delà de 1e-4 concerne `opening-64-match` à 2 plis (coup `8/2 6/2`, 9,5e-4). L'hypothèse la plus probable, non vérifiée : une petite différence fait basculer un choix discret de la recherche à 2 plis.
La tolérance de 0,002 vaut environ deux fois l'écart maximal mesuré, et 15 fois moins que le seuil où gnubg qualifie un coup de « douteux » (0,03).
Vérification par la session principale, après fusion de `main` (MR !7) dans la branche :
- `make setup && make engine && make lint && make test` : 7/7. La ligne de comparaison affiche « 32 positions, 64 niveaux, 2598 nombres comparés ; écart maximal 9.53e-04, tolérance 2e-03 » ;
- références altérées dans une copie (équité décalée de 0,01, décision de videau changée) : le comparateur échoue et liste exactement les 2 écarts.
## Choix et compromis
- **Le moteur reste en C générique**, et non en SSE2, sur PC. Une concordance au bit près serait possible, mais l'application tournera en C générique (WebAssembly) ou en NEON (Android) : c'est ce chemin qu'il faut tester.
- **Une tolérance unique** pour les probabilités et les équités : plus simple, et suffisante au regard des écarts mesurés.
- **Le format des nombres** d'`engine-cli` passe à 9 chiffres significatifs pour toutes les commandes : un peu moins lisible, mais exact.
## Risques et déploiement
- `make setup` reconstruit l'image `ustagammon/build-c` (étiquette 2).
- **Changement d'interface dans `engine.h`** (`engine_cube`) : aucun autre code ne l'utilise encore.
- **Sur téléphone, en NEON**, gnubg utilise une autre approximation de la division. L'écart devra y être mesuré de la même façon si le socle Android est retenu.
Retour arrière : annuler le commit de fusion.
## Comment vérifier
```
git switch main && git pull
make setup && make engine
make lint && make test
build/engine-cli --ply 2 reference 4HPwATDgc/ABMA cIkFAAAAAAAA 31
BUILD_C_IMAGE=ustagammon/build-c:2 bash tests/test_engine_reference.sh --details
```
## Hors périmètre
- La même suite de contrat sur le moteur WebAssembly : étape 0b, en cours.
- Les MR de ce dépôt restent affichées « open » après fusion, à cause des hooks git du serveur Gitea (diagnostic à part) ; Pierre les marque fusionnées dans l'interface.
Generated with Claude Code https://claude.com/claude-code
- engine_best_moves suit hint_move de gnubg : fAnalyse vrai, seuil
« douteux », puis RefreshMoveList (classement par niveau d'évaluation
et départage des égalités).
- Correction : en match, l'équité des coups était convertie deux fois par
mwc2eq (ScoreMove la convertit déjà).
- engine_cube : ajout de optimal et decision_text ; decision prend le nom
de l'énumération cubedecision de gnubg, comme les références.
- engine-cli : commande reference (un niveau au format de
tests/reference/) et nombres écrits avec 9 chiffres significatifs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jq n'est plus utilisé sur le PC (ADR 0004) : tests/test_reference.sh se
relance dans l'image ustagammon/build-c:2, qui contient aussi Python 3
pour le comparateur du moteur.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/test_engine_reference.sh lance tests/reference/compare.py sur les
32 positions aux niveaux 0 et 2 plis. Tolérance de 0,002 mesurée et
justifiée dans tests/reference/README.md : écart maximal de 9,5e-4, avec
ou sans -ffast-math ; la cause est la sigmoïde approchée (_mm_rcp_ps) de
gnubg de bureau en SSE2, qu'un build SSE2 du moteur reproduit au bit près.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Pourquoi
Le moteur embarqué (MR !7) doit retrouver les résultats de GNU Backgammon de bureau (cadrage, ADR 0005), et c'est aux tests de le garantir, puisque le code n'est pas relu par un humain. C'est l'étape 0a.4 :
make testcompare automatiquementengine-cliaux 32 positions de référence produites par gnubg de bureau (MR !6), aux niveaux 0 et 2 plis, avec une tolérance mesurée et justifiée.La comparaison a fait apparaître deux vrais défauts du moteur embarqué, que les tests de la MR !7 ne voyaient pas. Ils sont corrigés ici.
Cette MR consigne aussi la validation par Pierre des outils de compilation et de test de l'étape 0 (amendement de l'ADR 0004).
Quoi
Défauts corrigés dans
engine/engine.c:mwc2eq;hintde gnubg. Il suit maintenant la même méthode :FindnSaveBestMovesavecfAnalyse, seuilarSkillLevel[SKILL_DOUBTFUL], puisRefreshMoveList.engine-cli --ply N reference POSITION_ID MATCH_ID [DÉS]: produit un objet de même structure queplies["N"]d'un fichier de référence (le contrat detests/reference/README.md). Les nombres sont écrits avec 9 chiffres significatifs, ce qui redonne exactement le float32.engine.h:engine_cubegagneoptimaletdecision_text;decisionprend les noms de gnubg (DOUBLE_TAKE,NODOUBLE_TAKE…).tests/reference/compare.pyettests/test_engine_reference.sh(lancé parmake test). Les critères :En cas d'écart, le rapport donne la position, le niveau, le champ, la valeur attendue, la valeur obtenue et l'écart.
Image
ustagammon/build-c:2: ajoute Python 3 et jq.tests/test_reference.shs'y exécute, etjqn'est plus utilisé sur le PC (ADR 0004).ADR 0004 amendé : table des outils validés par Pierre (ShellCheck, Node et
@cucumber/gherkin, Debian et gnubg de référence, gcc, make, GLib, Python 3, jq, Emscripten), tous dans Docker et jamais embarqués.Comment
Travail délégué à un sous-agent selon un plan écrit avant la délégation, supprimé à la clôture ; son résultat est repris ici.
Tolérance retenue : 0,002, mesurée sur 2 598 nombres :
-ffast-math(build retenu)-ffast-mathL'écart vient du gnubg de bureau, pas de notre build. Compilé en SSE2 avec
-ffast-math, gnubg calcule l'inverse dans sa sigmoïde avec_mm_rcp_ps, une instruction approchée (environ 12 bits), alors que le C générique fait une vraie division. La preuve : compilé en SSE2, notre moteur redonne les références au bit près.Le seul écart au-delà de 1e-4 concerne
opening-64-matchà 2 plis (coup8/2 6/2, 9,5e-4). L'hypothèse la plus probable, non vérifiée : une petite différence fait basculer un choix discret de la recherche à 2 plis.La tolérance de 0,002 vaut environ deux fois l'écart maximal mesuré, et 15 fois moins que le seuil où gnubg qualifie un coup de « douteux » (0,03).
Vérification par la session principale, après fusion de
main(MR !7) dans la branche :make setup && make engine && make lint && make test: 7/7. La ligne de comparaison affiche « 32 positions, 64 niveaux, 2598 nombres comparés ; écart maximal 9.53e-04, tolérance 2e-03 » ;Choix et compromis
engine-clipasse à 9 chiffres significatifs pour toutes les commandes : un peu moins lisible, mais exact.Risques et déploiement
make setupreconstruit l'imageustagammon/build-c(étiquette 2).engine.h(engine_cube) : aucun autre code ne l'utilise encore.Retour arrière : annuler le commit de fusion.
Comment vérifier
Hors périmètre
Generated with Claude Code https://claude.com/claude-code