- 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>
161 lines
6.6 KiB
C
161 lines
6.6 KiB
C
/*
|
|
* engine.h -- interface C du moteur de backgammon d'Ustagammon.
|
|
*
|
|
* Copyright (C) 2026 les auteurs d'Ustagammon.
|
|
* Licence : GPLv3 ou ultérieure (voir LICENSE).
|
|
*
|
|
* Le moteur est le cœur de GNU Backgammon (engine/gnubg/), seule autorité
|
|
* pour les règles, les coups, le videau et les évaluations. Cette interface
|
|
* n'expose aucun type de gnubg.
|
|
*
|
|
* Positions : une position est décrite par deux identifiants de gnubg,
|
|
* - le Position ID (14 caractères), qui code le plateau du point de vue du
|
|
* joueur au trait ;
|
|
* - le Match ID (12 caractères), qui code le reste : longueur du match (0 en
|
|
* partie libre), score, videau et son propriétaire, joueur au trait,
|
|
* Crawford, Jacoby. Les dés éventuellement codés dans le Match ID sont
|
|
* ignorés : les dés sont passés à part.
|
|
*
|
|
* Niveaux (« ply ») : réglages prédéfinis de gnubg, sans bruit, de 0
|
|
* (évaluation statique du réseau) à 4. gnubg compte les plis à partir de 0.
|
|
*
|
|
* Équités : toujours du point de vue du joueur au trait, normalisées pour
|
|
* un videau de 1. En match, gnubg convertit les chances de gain du match en
|
|
* équité normalisée, comme il l'affiche par défaut.
|
|
*
|
|
* Probabilités, dans l'ordre de gnubg : gain, gain gammon, gain backgammon,
|
|
* perte gammon, perte backgammon (les gammons incluent les backgammons).
|
|
*
|
|
* Contraintes : une seule instance du moteur (état global de gnubg) et des
|
|
* appels sérialisés, jamais concurrents. Toutes les fonctions renvoient un
|
|
* code engine_status ; aucune ne termine le programme pour une erreur
|
|
* d'utilisation.
|
|
*/
|
|
|
|
#ifndef USTAGAMMON_ENGINE_H
|
|
#define USTAGAMMON_ENGINE_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef enum {
|
|
ENGINE_OK = 0,
|
|
ENGINE_ERROR_NOT_INITIALISED, /* engine_init n'a pas réussi */
|
|
ENGINE_ERROR_DATA, /* données absentes ou invalides */
|
|
ENGINE_ERROR_POSITION_ID, /* Position ID invalide */
|
|
ENGINE_ERROR_MATCH_ID, /* Match ID invalide */
|
|
ENGINE_ERROR_DICE, /* dés hors de 1..6 */
|
|
ENGINE_ERROR_PLY, /* niveau hors de 0..ENGINE_MAX_PLY */
|
|
ENGINE_ERROR_TOO_MANY_MOVES, /* tableau de coups trop petit */
|
|
ENGINE_ERROR_INTERNAL /* échec signalé par gnubg */
|
|
} engine_status;
|
|
|
|
#define ENGINE_MAX_PLY 4
|
|
|
|
/* Nombre maximal de coups légaux pour un jet (MAX_MOVES de gnubg). */
|
|
#define ENGINE_MAX_MOVES 3060
|
|
|
|
/* Indices du tableau probabilities. */
|
|
enum {
|
|
ENGINE_WIN = 0,
|
|
ENGINE_WIN_GAMMON,
|
|
ENGINE_WIN_BACKGAMMON,
|
|
ENGINE_LOSE_GAMMON,
|
|
ENGINE_LOSE_BACKGAMMON,
|
|
ENGINE_NUM_PROBABILITIES
|
|
};
|
|
|
|
/* Un coup, avec son évaluation quand il a été classé. */
|
|
typedef struct {
|
|
char notation[32]; /* notation de gnubg, ex. « 8/5 6/5 » */
|
|
char position_id[16]; /* Position ID après le coup, plateau vu du
|
|
* joueur qui vient de jouer */
|
|
int ply; /* niveau de l'évaluation (-1 : non évalué) */
|
|
float probabilities[ENGINE_NUM_PROBABILITIES];
|
|
float equity; /* équité de classement (avec videau) */
|
|
} engine_move;
|
|
|
|
/* Évaluation d'une position, joueur au trait avant de lancer les dés. */
|
|
typedef struct {
|
|
float probabilities[ENGINE_NUM_PROBABILITIES];
|
|
float cubeless_equity; /* équité sans videau */
|
|
float cubeful_equity; /* équité avec videau */
|
|
} engine_evaluation;
|
|
|
|
/* Décision de videau du joueur au trait, avant de lancer les dés. */
|
|
typedef struct {
|
|
float probabilities[ENGINE_NUM_PROBABILITIES];
|
|
float no_double; /* équité si pas de double */
|
|
float double_take; /* équité si double et prend */
|
|
float double_pass; /* équité si double et passe */
|
|
float optimal; /* équité après les meilleures décisions des deux
|
|
* joueurs */
|
|
const char *decision; /* nom de la décision dans l'énumération
|
|
* cubedecision de gnubg : « NODOUBLE_TAKE »,
|
|
* « DOUBLE_TAKE », « DOUBLE_PASS »,
|
|
* « TOOGOOD_PASS », « NOT_AVAILABLE »… */
|
|
const char *decision_text; /* libellé anglais de gnubg, ex. « Double, take » */
|
|
} engine_cube;
|
|
|
|
/* Description lisible d'un Match ID décodé. */
|
|
typedef struct {
|
|
int match_length; /* 0 : partie libre (money game) */
|
|
int score[2];
|
|
int cube_value;
|
|
int cube_owner; /* -1 : videau au centre ; sinon 0 ou 1 */
|
|
int player_on_roll; /* 0 ou 1 */
|
|
int crawford; /* partie Crawford en cours */
|
|
int jacoby; /* règle Jacoby (partie libre) */
|
|
} engine_match;
|
|
|
|
/*
|
|
* Charge les données du moteur depuis data_dir : gnubg.wd (réseaux),
|
|
* gnubg_os0.bd et gnubg_ts0.bd (fins de partie), Kazaross-XG2.xml (table
|
|
* d'équité de match). À appeler une fois avant toute autre fonction.
|
|
*/
|
|
engine_status engine_init(const char *data_dir);
|
|
|
|
/* Libère les ressources. Le moteur ne peut pas être réinitialisé ensuite. */
|
|
void engine_shutdown(void);
|
|
|
|
/* Message d'erreur en français pour un code de retour. */
|
|
const char *engine_status_message(engine_status status);
|
|
|
|
/* Décode un Match ID. */
|
|
engine_status engine_decode_match(const char *match_id, engine_match *match);
|
|
|
|
/*
|
|
* Coups légaux pour une position et un jet (die1, die2 dans 1..6), sans
|
|
* évaluation (ply vaut -1). moves doit pouvoir contenir max_moves coups ;
|
|
* ENGINE_MAX_MOVES suffit toujours. *count reçoit le nombre de coups (0 si
|
|
* le joueur ne peut pas jouer).
|
|
*/
|
|
engine_status engine_legal_moves(const char *position_id, const char *match_id,
|
|
int die1, int die2,
|
|
engine_move *moves, int max_moves, int *count);
|
|
|
|
/*
|
|
* Coups légaux classés du meilleur au moins bon, au niveau ply, exactement
|
|
* comme la commande « hint » de gnubg (filtre de coups « Normal »). Les coups
|
|
* écartés par les filtres gardent l'évaluation du niveau inférieur (voir
|
|
* leur champ ply) et sont classés après ceux évalués plus profondément.
|
|
*/
|
|
engine_status engine_best_moves(const char *position_id, const char *match_id,
|
|
int die1, int die2, int ply,
|
|
engine_move *moves, int max_moves, int *count);
|
|
|
|
/* Évaluation d'une position au niveau ply. */
|
|
engine_status engine_evaluate(const char *position_id, const char *match_id,
|
|
int ply, engine_evaluation *evaluation);
|
|
|
|
/* Décision de videau au niveau ply. */
|
|
engine_status engine_cube_decision(const char *position_id, const char *match_id,
|
|
int ply, engine_cube *cube);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* USTAGAMMON_ENGINE_H */
|