Étape 0a.3 de la feuille de route : faire du cœur de GNU Backgammon une bibliothèque C autonome, sans GLib ni interface graphique, cachée derrière une interface propre à Ustagammon. C'est la brique que l'application embarquera, en WebAssembly ou sur Android. L'ADR 0005 a fixé la source (gnubg officiel, commit 14b67984737ded0f6de43d63dcb789f729d9b06b) et le plan d'isolement ; l'ADR 0007 impose des identifiants en anglais, d'où engine.h au lieu de moteur.h.
Quoi
engine/gnubg/ : copie figée de 38 fichiers de gnubg et de son COPYING. Aucun fichier n'est modifié : le sous-agent l'a vérifié avec cmp contre le clone, et la liste est dans engine/gnubg/PROVENANCE.md. Par rapport à la liste de l'ADR 0005, il a fallu ajouter drawboard.c/h (notation des coups), mtsupport.c et dice.h.
engine/data/ : gnubg.weights et Kazaross-XG2.xml, copiés tels quels.
engine/compat/ : notre couche de compatibilité.
un config.h écrit à la main : sans threads, C générique sur x86, chemin NEON prévu mais pas encore compilé ;
un shim GLib minimal, avec un petit analyseur XML compatible GMarkup pour les tables d'équité de match ;
des en-têtes réduits à la place de backgammon.h et consorts ;
les fonctions de support que gnubg attend ; le stubs.c de CBG a servi de repère, sans reprise de code.
engine/include/engine.h : l'interface. Fonctions engine_init, engine_shutdown, engine_decode_match, engine_legal_moves, engine_best_moves, engine_evaluate et engine_cube_decision. Positions en Position ID + Match ID, niveaux 0 à 4 (réglages prédéfinis de gnubg, sans bruit), erreurs par code de retour. Les données manquantes sont vérifiées avant d'appeler gnubg, dont l'initialisation ferait sinon un exit().
engine-cli/main.c : sous-commandes bestmove, moves, legal, cube et eval, options --ply et --data, sortie JSON. En cas d'erreur, il renvoie du JSON et un code de sortie non nul.
Build :
make engine compile dans Docker, avec l'image ustagammon/build-c:1 (docker/build-c/Dockerfile, Debian trixie, gcc, make, et GLib uniquement pour les outils de génération) ;
make build l'appelle, make setup construit l'image ;
code gnubg compilé avec ses options officielles, notre C en -std=c11 -Wall -Wextra -Werror ;
gnubg.wd et les bases de fin de partie sont générés dans build/ par les outils officiels, avec les paramètres du build officiel ;
une recompilation ne refait rien si rien n'a changé.
tests/test_engine.sh (lancé par make test) :
ouvertures 31, 42, 53 et 61 à 0 et 2 plis ;
nombre de coups légaux d'une course construite à la main ;
bornes et cohérence des probabilités, symétrie selon le joueur au trait ;
décisions de videau évidentes (pas de double au départ, videau mort en Crawford, double/passe dans une course gagnée) ;
8 cas d'erreur.
tests/test_makefile.sh ne vide plus le vrai build/ (sinon chaque make test forçait une recompilation du moteur). tests/lint.sh n'impose pas nos règles d'espaces aux copies fidèles de gnubg.
Comment
Le travail a été 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. Pour les tables d'équité, l'analyseur XML du shim permet à matchequity.c de lire Kazaross-XG2.xml comme le fait gnubg de bureau. engine_init échoue si gnubg se rabat en silence sur une autre table. Le sous-agent a contre-vérifié en liant une variante d'engine-cli à la vraie GLib : la sortie est identique au caractère près sur 6 cas (partie libre, match, Crawford, 0 et 2 plis).
Vérification par la session principale, sur la branche fusionnée avec main :
make setup && make engine : 47 s depuis zéro ; un second make engine répond « Nothing to be done » ;
./build/engine-cli bestmove 4HPwATDgc/ABMA MAEAAAAAAAAA 31 → 8/5 6/5 ; à 2 plis, le 64 d'ouverture → 24/18 13/9 en 0,14 s ;
gnubg.wd, gnubg_os0.bd et gnubg_ts0.bd générés ici ont les mêmes SHA-256 que ceux de l'image du gnubg de référence (MR !6) ;
make lint et make test : 6/6.
Choix et compromis
Aucune modification des fichiers de gnubg : tout l'écart passe par engine/compat/. Une mise à jour de gnubg se résume alors à recopier les fichiers et à vérifier la couche de compatibilité.
Analyseur XML plutôt que conversion des tables en C : la table reste lue comme dans gnubg de bureau, ce qui limite les risques d'écart, au prix d'un petit analyseur à maintenir dans le shim.
État global de gnubg : une seule instance du moteur, pas de réinitialisation après engine_shutdown. C'est une limite assumée (ADR 0005).
Le pli rapporté peut être 1 dans un résultat demandé à 2 plis : c'est le comportement de gnubg quand un seul coup survit aux filtres, et c'est cohérent avec les références (champ ply de chaque coup).
engine-cli a une sous-commande de plus que prévu, legal, qui liste les coups sans évaluation.
Risques et déploiement
Nouvelle dépendance de build, soumise à la validation de Pierre (docs/organisation.md) : l'image ustagammon/build-c, qui contient gcc et make (GPLv3), plus GLib (LGPL 2.1+) uniquement pour compiler les outils officiels makeweights et makebearoff. Rien de GLib n'est embarqué dans le moteur. Ces éléments sont crédités dans CREDITS.md.
make setup construit une image de plus (quelques minutes la première fois).
Match ID : cAkAAAAAAAAA, utilisé jusqu'ici comme exemple de « partie libre, joueur 0 au trait », met en fait le joueur 1 au trait. L'équivalent avec le joueur 0 au trait est MAEAAAAAAAAA. Sur la position de départ, les deux donnent le même résultat. Les références qui utilisent cAkAAAAAAAAA restent justes, puisque générées et relues par gnubg lui-même.
Retour arrière : annuler le commit de fusion ; build/ se supprime avec make clean.
Comment vérifier
git switch main && git pull
make setup
make engine
./build/engine-cli bestmove 4HPwATDgc/ABMA MAEAAAAAAAAA 31
./build/engine-cli cube 4HPwATDgc/ABMA MAEAAAAAAAAA
make engine # Nothing to be done
make lint && make test
Hors périmètre
La comparaison systématique avec les 32 positions de référence et la mesure de l'écart dû à -ffast-math : étape 0a.4, qui suit.
jq utilisé sur le PC par tests/test_reference.sh (ADR 0004) : corrigé à l'étape 0a.4, en passant par l'image build-c.
La compilation NEON (ARM) et WebAssembly : étape 0b ou 0c.
Les MR de ce dépôt restent affichées « open » après fusion : les hooks git du serveur Gitea ne s'exécutent pas (diagnostic à part).
## Pourquoi
Étape 0a.3 de la feuille de route : faire du cœur de GNU Backgammon une bibliothèque C autonome, sans GLib ni interface graphique, cachée derrière une interface propre à Ustagammon. C'est la brique que l'application embarquera, en WebAssembly ou sur Android. L'ADR 0005 a fixé la source (gnubg officiel, commit 14b67984737ded0f6de43d63dcb789f729d9b06b) et le plan d'isolement ; l'ADR 0007 impose des identifiants en anglais, d'où `engine.h` au lieu de `moteur.h`.
## Quoi
- **`engine/gnubg/`** : copie figée de 38 fichiers de gnubg et de son `COPYING`. **Aucun fichier n'est modifié** : le sous-agent l'a vérifié avec `cmp` contre le clone, et la liste est dans `engine/gnubg/PROVENANCE.md`. Par rapport à la liste de l'ADR 0005, il a fallu ajouter `drawboard.c/h` (notation des coups), `mtsupport.c` et `dice.h`.
- **`engine/data/`** : `gnubg.weights` et `Kazaross-XG2.xml`, copiés tels quels.
- **`engine/compat/`** : notre couche de compatibilité.
- un `config.h` écrit à la main : sans threads, C générique sur x86, chemin NEON prévu mais pas encore compilé ;
- un shim GLib minimal, avec un petit analyseur XML compatible GMarkup pour les tables d'équité de match ;
- des en-têtes réduits à la place de `backgammon.h` et consorts ;
- les fonctions de support que gnubg attend ; le `stubs.c` de CBG a servi de repère, sans reprise de code.
- **`engine/include/engine.h`** : l'interface. Fonctions `engine_init`, `engine_shutdown`, `engine_decode_match`, `engine_legal_moves`, `engine_best_moves`, `engine_evaluate` et `engine_cube_decision`. Positions en Position ID + Match ID, niveaux 0 à 4 (réglages prédéfinis de gnubg, sans bruit), erreurs par code de retour. Les données manquantes sont vérifiées avant d'appeler gnubg, dont l'initialisation ferait sinon un `exit()`.
- **`engine-cli/main.c`** : sous-commandes `bestmove`, `moves`, `legal`, `cube` et `eval`, options `--ply` et `--data`, sortie JSON. En cas d'erreur, il renvoie du JSON et un code de sortie non nul.
- **Build** :
- `make engine` compile dans Docker, avec l'image `ustagammon/build-c:1` (`docker/build-c/Dockerfile`, Debian trixie, gcc, make, et GLib uniquement pour les outils de génération) ;
- `make build` l'appelle, `make setup` construit l'image ;
- code gnubg compilé avec ses options officielles, notre C en `-std=c11 -Wall -Wextra -Werror` ;
- `gnubg.wd` et les bases de fin de partie sont générés dans `build/` par les outils officiels, avec les paramètres du build officiel ;
- une recompilation ne refait rien si rien n'a changé.
- **`tests/test_engine.sh`** (lancé par `make test`) :
- ouvertures 31, 42, 53 et 61 à 0 et 2 plis ;
- nombre de coups légaux d'une course construite à la main ;
- bornes et cohérence des probabilités, symétrie selon le joueur au trait ;
- décisions de videau évidentes (pas de double au départ, videau mort en Crawford, double/passe dans une course gagnée) ;
- 8 cas d'erreur.
- `tests/test_makefile.sh` ne vide plus le vrai `build/` (sinon chaque `make test` forçait une recompilation du moteur). `tests/lint.sh` n'impose pas nos règles d'espaces aux copies fidèles de gnubg.
## Comment
Le travail a été 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. Pour les tables d'équité, l'analyseur XML du shim permet à `matchequity.c` de lire `Kazaross-XG2.xml` comme le fait gnubg de bureau. `engine_init` échoue si gnubg se rabat en silence sur une autre table. Le sous-agent a contre-vérifié en liant une variante d'`engine-cli` à la vraie GLib : la sortie est identique au caractère près sur 6 cas (partie libre, match, Crawford, 0 et 2 plis).
Vérification par la session principale, sur la branche fusionnée avec `main` :
- `make setup && make engine` : 47 s depuis zéro ; un second `make engine` répond « Nothing to be done » ;
- `./build/engine-cli bestmove 4HPwATDgc/ABMA MAEAAAAAAAAA 31` → `8/5 6/5` ; à 2 plis, le 64 d'ouverture → `24/18 13/9` en 0,14 s ;
- `gnubg.wd`, `gnubg_os0.bd` et `gnubg_ts0.bd` générés ici ont **les mêmes SHA-256** que ceux de l'image du gnubg de référence (MR !6) ;
- `make lint` et `make test` : 6/6.
## Choix et compromis
- **Aucune modification des fichiers de gnubg** : tout l'écart passe par `engine/compat/`. Une mise à jour de gnubg se résume alors à recopier les fichiers et à vérifier la couche de compatibilité.
- **Analyseur XML plutôt que conversion des tables en C** : la table reste lue comme dans gnubg de bureau, ce qui limite les risques d'écart, au prix d'un petit analyseur à maintenir dans le shim.
- **État global de gnubg** : une seule instance du moteur, pas de réinitialisation après `engine_shutdown`. C'est une limite assumée (ADR 0005).
- **Le pli rapporté peut être 1 dans un résultat demandé à 2 plis** : c'est le comportement de gnubg quand un seul coup survit aux filtres, et c'est cohérent avec les références (champ `ply` de chaque coup).
- **`engine-cli` a une sous-commande de plus que prévu**, `legal`, qui liste les coups sans évaluation.
## Risques et déploiement
- **Nouvelle dépendance de build**, soumise à la validation de Pierre (`docs/organisation.md`) : l'image `ustagammon/build-c`, qui contient gcc et make (GPLv3), plus GLib (LGPL 2.1+) uniquement pour compiler les outils officiels `makeweights` et `makebearoff`. Rien de GLib n'est embarqué dans le moteur. Ces éléments sont crédités dans `CREDITS.md`.
- `make setup` construit une image de plus (quelques minutes la première fois).
- **Match ID** : `cAkAAAAAAAAA`, utilisé jusqu'ici comme exemple de « partie libre, joueur 0 au trait », met en fait le joueur 1 au trait. L'équivalent avec le joueur 0 au trait est `MAEAAAAAAAAA`. Sur la position de départ, les deux donnent le même résultat. Les références qui utilisent `cAkAAAAAAAAA` restent justes, puisque générées et relues par gnubg lui-même.
Retour arrière : annuler le commit de fusion ; `build/` se supprime avec `make clean`.
## Comment vérifier
```
git switch main && git pull
make setup
make engine
./build/engine-cli bestmove 4HPwATDgc/ABMA MAEAAAAAAAAA 31
./build/engine-cli cube 4HPwATDgc/ABMA MAEAAAAAAAAA
make engine # Nothing to be done
make lint && make test
```
## Hors périmètre
- La comparaison systématique avec les 32 positions de référence et la mesure de l'écart dû à `-ffast-math` : étape 0a.4, qui suit.
- `jq` utilisé sur le PC par `tests/test_reference.sh` (ADR 0004) : corrigé à l'étape 0a.4, en passant par l'image `build-c`.
- La compilation NEON (ARM) et WebAssembly : étape 0b ou 0c.
- Les MR de ce dépôt restent affichées « open » après fusion : les hooks git du serveur Gitea ne s'exécutent pas (diagnostic à part).
Generated with Claude Code https://claude.com/claude-code
Fichiers repris sans modification dans engine/gnubg/, poids et table
d'équité Kazaross-XG2 dans engine/data/, provenance détaillée dans
engine/gnubg/PROVENANCE.md. Le lint ne vérifie plus les espaces de ces
copies, pour qu'elles restent identiques à l'original.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
engine/compat/ remplace ce que le cœur de gnubg attend du reste de gnubg
et de GLib : config.h écrit à la main (sans threads, C générique, NEON
prévu), shim GLib minimal (dont un analyseur XML pour les tables d'équité
et mmap pour les bases de fin de partie), en-têtes réduits et fonctions de
support.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
engine.h expose initialisation, coups légaux, classement des coups,
évaluation et décision de videau, avec Position ID et Match ID, sans type
gnubg ; erreurs par code de retour. engine-cli l'interroge et répond en
JSON (bestmove, moves, legal, cube, eval ; option --ply).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Image ustagammon/build-c (Debian trixie, gcc, GLib pour les seuls outils
de génération), construite par make setup. engine/engine.mk compile le
moteur et engine-cli, et génère gnubg.wd et les bases .bd avec makeweights
et makebearoff, comme le Makefile.am de gnubg. Dépendances suivies : un
second make engine ne recompile rien. make build appelle make engine.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/test_engine.sh : coups d'ouverture connus à 0 et 2 plis, nombre de
coups légaux, bornes et symétrie des probabilités, décisions de videau
évidentes, erreurs. test_makefile.sh essaie make clean sur un dossier
jetable, pour ne plus forcer la recompilation du moteur à chaque test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fusion du travail du sous-agent (branche moteur-embarque-travail) ; plan
supprimé à la clôture, son résultat est repris dans la merge request.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pierre
manually merged commit 51801e8491 into main2026-11-02 18:03:48 +00:00
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
Étape 0a.3 de la feuille de route : faire du cœur de GNU Backgammon une bibliothèque C autonome, sans GLib ni interface graphique, cachée derrière une interface propre à Ustagammon. C'est la brique que l'application embarquera, en WebAssembly ou sur Android. L'ADR 0005 a fixé la source (gnubg officiel, commit 14b67984737ded0f6de43d63dcb789f729d9b06b) et le plan d'isolement ; l'ADR 0007 impose des identifiants en anglais, d'où
engine.hau lieu demoteur.h.Quoi
engine/gnubg/: copie figée de 38 fichiers de gnubg et de sonCOPYING. Aucun fichier n'est modifié : le sous-agent l'a vérifié aveccmpcontre le clone, et la liste est dansengine/gnubg/PROVENANCE.md. Par rapport à la liste de l'ADR 0005, il a fallu ajouterdrawboard.c/h(notation des coups),mtsupport.cetdice.h.engine/data/:gnubg.weightsetKazaross-XG2.xml, copiés tels quels.engine/compat/: notre couche de compatibilité.config.hécrit à la main : sans threads, C générique sur x86, chemin NEON prévu mais pas encore compilé ;backgammon.het consorts ;stubs.cde CBG a servi de repère, sans reprise de code.engine/include/engine.h: l'interface. Fonctionsengine_init,engine_shutdown,engine_decode_match,engine_legal_moves,engine_best_moves,engine_evaluateetengine_cube_decision. Positions en Position ID + Match ID, niveaux 0 à 4 (réglages prédéfinis de gnubg, sans bruit), erreurs par code de retour. Les données manquantes sont vérifiées avant d'appeler gnubg, dont l'initialisation ferait sinon unexit().engine-cli/main.c: sous-commandesbestmove,moves,legal,cubeeteval, options--plyet--data, sortie JSON. En cas d'erreur, il renvoie du JSON et un code de sortie non nul.make enginecompile dans Docker, avec l'imageustagammon/build-c:1(docker/build-c/Dockerfile, Debian trixie, gcc, make, et GLib uniquement pour les outils de génération) ;make buildl'appelle,make setupconstruit l'image ;-std=c11 -Wall -Wextra -Werror;gnubg.wdet les bases de fin de partie sont générés dansbuild/par les outils officiels, avec les paramètres du build officiel ;tests/test_engine.sh(lancé parmake test) :tests/test_makefile.shne vide plus le vraibuild/(sinon chaquemake testforçait une recompilation du moteur).tests/lint.shn'impose pas nos règles d'espaces aux copies fidèles de gnubg.Comment
Le travail a été 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. Pour les tables d'équité, l'analyseur XML du shim permet à
matchequity.cde lireKazaross-XG2.xmlcomme le fait gnubg de bureau.engine_initéchoue si gnubg se rabat en silence sur une autre table. Le sous-agent a contre-vérifié en liant une variante d'engine-clià la vraie GLib : la sortie est identique au caractère près sur 6 cas (partie libre, match, Crawford, 0 et 2 plis).Vérification par la session principale, sur la branche fusionnée avec
main:make setup && make engine: 47 s depuis zéro ; un secondmake enginerépond « Nothing to be done » ;./build/engine-cli bestmove 4HPwATDgc/ABMA MAEAAAAAAAAA 31→8/5 6/5; à 2 plis, le 64 d'ouverture →24/18 13/9en 0,14 s ;gnubg.wd,gnubg_os0.bdetgnubg_ts0.bdgénérés ici ont les mêmes SHA-256 que ceux de l'image du gnubg de référence (MR !6) ;make lintetmake test: 6/6.Choix et compromis
engine/compat/. Une mise à jour de gnubg se résume alors à recopier les fichiers et à vérifier la couche de compatibilité.engine_shutdown. C'est une limite assumée (ADR 0005).plyde chaque coup).engine-clia une sous-commande de plus que prévu,legal, qui liste les coups sans évaluation.Risques et déploiement
docs/organisation.md) : l'imageustagammon/build-c, qui contient gcc et make (GPLv3), plus GLib (LGPL 2.1+) uniquement pour compiler les outils officielsmakeweightsetmakebearoff. Rien de GLib n'est embarqué dans le moteur. Ces éléments sont crédités dansCREDITS.md.make setupconstruit une image de plus (quelques minutes la première fois).cAkAAAAAAAAA, utilisé jusqu'ici comme exemple de « partie libre, joueur 0 au trait », met en fait le joueur 1 au trait. L'équivalent avec le joueur 0 au trait estMAEAAAAAAAAA. Sur la position de départ, les deux donnent le même résultat. Les références qui utilisentcAkAAAAAAAAArestent justes, puisque générées et relues par gnubg lui-même.Retour arrière : annuler le commit de fusion ;
build/se supprime avecmake clean.Comment vérifier
Hors périmètre
-ffast-math: étape 0a.4, qui suit.jqutilisé sur le PC partests/test_reference.sh(ADR 0004) : corrigé à l'étape 0a.4, en passant par l'imagebuild-c.Generated with Claude Code https://claude.com/claude-code