Moteur : plateau, fin de partie, Match ID et saisie demi-coup par demi-coup
Ce dont le domaine d'une partie a besoin, sans réimplémenter de règle : décodage d'un Position ID en plateau et position vue de l'adversaire, résultat d'une partie finie (gammon, règle Jacoby), codage d'un Match ID, vérification de demi-coups saisis un par un (la légalité vient de GenerateMoves de gnubg), demi-coups de chaque coup légal, droit de doubler et recommandations de double et de prise. Nouvelles commandes d'engine-cli position, halfmoves et matchid, avec leurs tests natifs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
03b26ccba7
commit
6af82f73b0
@@ -66,11 +66,29 @@ enum {
|
||||
ENGINE_NUM_PROBABILITIES
|
||||
};
|
||||
|
||||
/*
|
||||
* Demi-coup : une dame déplacée d'une case avec un seul dé. Les cases sont
|
||||
* numérotées du point de vue du joueur qui joue, comme dans la notation de
|
||||
* gnubg : 1 à 24, 25 pour la barre, 0 pour la sortie.
|
||||
*/
|
||||
#define ENGINE_BAR 25
|
||||
#define ENGINE_OFF 0
|
||||
|
||||
typedef struct {
|
||||
int from;
|
||||
int to;
|
||||
} engine_half_move;
|
||||
|
||||
/* Un coup complet utilise au plus quatre dés (un double). */
|
||||
#define ENGINE_MAX_HALF_MOVES 4
|
||||
|
||||
/* 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 */
|
||||
engine_half_move half_moves[ENGINE_MAX_HALF_MOVES];
|
||||
int half_move_count; /* demi-coups du coup, dans un ordre jouable */
|
||||
int ply; /* niveau de l'évaluation (-1 : non évalué) */
|
||||
float probabilities[ENGINE_NUM_PROBABILITIES];
|
||||
float equity; /* équité de classement (avec videau) */
|
||||
@@ -96,8 +114,50 @@ typedef struct {
|
||||
* « DOUBLE_TAKE », « DOUBLE_PASS »,
|
||||
* « TOOGOOD_PASS », « NOT_AVAILABLE »… */
|
||||
const char *decision_text; /* libellé anglais de gnubg, ex. « Double, take » */
|
||||
int available; /* le joueur au trait a le droit de doubler */
|
||||
int should_double; /* gnubg recommande de doubler : décision
|
||||
* DOUBLE_TAKE, DOUBLE_PASS, DOUBLE_BEAVER,
|
||||
* REDOUBLE_TAKE ou REDOUBLE_PASS (un double
|
||||
* « facultatif » n'est pas recommandé) */
|
||||
int should_take; /* s'il double, l'adversaire doit prendre :
|
||||
* prendre lui coûte moins que passer
|
||||
* (double_take <= double_pass) */
|
||||
} engine_cube;
|
||||
|
||||
/* Un camp sur le plateau, vu de lui-même (sa case 1 est la plus proche de
|
||||
* la sortie). */
|
||||
typedef struct {
|
||||
int points[24]; /* dames sur les cases 1 à 24 (indices 0 à 23) */
|
||||
int bar; /* dames sur la barre */
|
||||
int off; /* dames sorties */
|
||||
int pip_count; /* compte de points */
|
||||
} engine_side;
|
||||
|
||||
/* Plateau décodé d'un Position ID. */
|
||||
typedef struct {
|
||||
engine_side on_roll; /* le joueur au trait */
|
||||
engine_side opponent; /* son adversaire */
|
||||
char swapped_position_id[16]; /* la même position vue de l'adversaire */
|
||||
} engine_board;
|
||||
|
||||
/* Fin de partie. */
|
||||
typedef struct {
|
||||
int over; /* la partie est finie */
|
||||
int winner; /* 0 : le joueur au trait, 1 : son adversaire */
|
||||
int kind; /* 1 : simple, 2 : gammon, 3 : backgammon */
|
||||
int points; /* points gagnés : kind fois la valeur du videau,
|
||||
* mais 1 fois en partie libre avec la règle
|
||||
* Jacoby quand le videau n'a pas bougé */
|
||||
} engine_result;
|
||||
|
||||
/* Où en est un coup saisi demi-coup par demi-coup. */
|
||||
typedef struct {
|
||||
int valid; /* les demi-coups commencent un coup légal */
|
||||
int complete; /* ils forment à eux seuls un coup légal */
|
||||
char position_id[16]; /* si valid : position après ces demi-coups, vue
|
||||
* du joueur qui joue ; sinon chaîne vide */
|
||||
} engine_half_moves_check;
|
||||
|
||||
/* Description lisible d'un Match ID décodé. */
|
||||
typedef struct {
|
||||
int match_length; /* 0 : partie libre (money game) */
|
||||
@@ -125,6 +185,30 @@ 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);
|
||||
|
||||
/*
|
||||
* Code un Match ID (12 caractères et le zéro final), sans dés ni double en
|
||||
* cours. cube_value : puissance de 2 de 1 à 4096 ; cube_owner : -1, 0 ou 1.
|
||||
*/
|
||||
engine_status engine_encode_match(const engine_match *match, char match_id[13]);
|
||||
|
||||
/* Décode un Position ID en plateau. */
|
||||
engine_status engine_decode_position(const char *position_id, engine_board *board);
|
||||
|
||||
/* La partie est-elle finie dans cette position, et combien rapporte-t-elle ? */
|
||||
engine_status engine_game_result(const char *position_id, const char *match_id,
|
||||
engine_result *result);
|
||||
|
||||
/*
|
||||
* Vérifie des demi-coups saisis un par un (count de 0 à
|
||||
* ENGINE_MAX_HALF_MOVES), avec le jet die1, die2 : chacun doit être permis
|
||||
* par les règles, et l'ensemble doit pouvoir se compléter en un des coups
|
||||
* légaux d'engine_legal_moves. Des demi-coups refusés ne sont pas une erreur :
|
||||
* check->valid vaut alors 0.
|
||||
*/
|
||||
engine_status engine_check_half_moves(const char *position_id, int die1, int die2,
|
||||
const engine_half_move *half_moves, int count,
|
||||
engine_half_moves_check *check);
|
||||
|
||||
/*
|
||||
* 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 ;
|
||||
|
||||
Reference in New Issue
Block a user