Domaine et adaptateur : niveaux, analyses et chance ; cache vidé à chaque calcul

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Pierre MARTIN
2026-11-03 14:59:07 +01:00
co-authored by Claude Opus 5.5
parent 2f6eb86972
commit 23f4d47fcf
9 changed files with 476 additions and 4 deletions
+135
View File
@@ -38,6 +38,141 @@ export interface Engine {
/** Le plateau d'une position, et le résultat si la partie y est finie. */
board(position: PositionId, cube: EngineCube): Promise<Board>;
/** Le coup que joue l'ordinateur de gnubg à ce niveau (bruit compris,
* reproductible), ou null si aucun coup n'est possible. */
levelMove(
position: PositionId,
cube: EngineCube,
roll: Roll,
level: Level,
): Promise<Move | null>;
/** La décision de videau de l'ordinateur à ce niveau, bruit compris. */
levelCubeDecision(position: PositionId, cube: EngineCube, level: Level): Promise<CubeDecision>;
/** L'analyse du coup joué (played : position après le coup, vue du joueur
* qui l'a joué, comme Move.position), au niveau d'analyse ply ; null si
* aucun coup n'était possible. */
analyseMove(
position: PositionId,
cube: EngineCube,
roll: Roll,
played: PositionId,
ply: Ply,
): Promise<MoveAnalysis | null>;
/** L'analyse d'une décision de videau, position vue du joueur au trait
* (celui qui double ou non ; take et pass sont la réponse de son
* adversaire). */
analyseCube(
position: PositionId,
cube: EngineCube,
action: CubeAction,
ply: Ply,
): Promise<CubeAnalysis>;
/** La chance d'un jet pour le joueur au trait. */
luck(position: PositionId, cube: EngineCube, roll: Roll): Promise<Luck>;
}
/**
* Niveau de jeu de l'ordinateur : un réglage prédéfini de GNU Backgammon
* (aecSettings dans eval.c ; voir engine/include/engine.h). Les quatre
* premiers jouent à 0 pli avec un bruit qui leur fait commettre des erreurs ;
* les suivants sont sans bruit, de 0 à 4 plis.
*
* Glossaire : docs/glossaire/niveau-de-jeu.md
*/
export type Level =
| "beginner"
| "casual"
| "intermediate"
| "advanced"
| "0ply"
| "1ply"
| "2ply"
| "3ply"
| "4ply";
/**
* Appréciation d'un coup ou d'une décision de videau par le moteur, selon
* l'équité perdue : rien à signaler, douteux, mauvais, très mauvais.
*
* Glossaire : docs/glossaire/appreciation.md
*/
export type Skill = "none" | "doubtful" | "bad" | "veryBad";
/**
* Seuils de GNU Backgammon (arSkillLevel dans gnubg.c) : une perte
* d'équité strictement plus grande fait passer à l'appréciation. Le moteur
* classe lui-même ; ces valeurs servent à l'expliquer.
*/
export const SKILL_THRESHOLDS = { doubtful: 0.03, bad: 0.06, veryBad: 0.12 } as const;
/** Catégorie de chance d'un jet, de très malchanceux à très chanceux. */
export type LuckRating = "veryUnlucky" | "unlucky" | "none" | "lucky" | "veryLucky";
/**
* Seuils de GNU Backgammon (arLuckLevel dans gnubg.c) sur la chance d'un
* jet, dans un sens ou dans l'autre.
*/
export const LUCK_THRESHOLDS = { lucky: 0.3, veryLucky: 0.6 } as const;
/**
* La chance d'un jet : l'équité qu'il fait gagner (positive) ou perdre au
* joueur par rapport à la moyenne des jets.
*
* Glossaire : docs/glossaire/chance.md
*/
export interface Luck {
readonly value: number;
readonly rating: LuckRating;
}
/** Un coup avec son équité (avec videau), du point de vue de celui qui le joue. */
export interface EvaluatedMove extends Move {
readonly equity: number;
/** Niveau auquel le coup a réellement été évalué. */
readonly ply: Ply;
}
/** Ce que le moteur dit d'un coup joué, comme l'analyse de partie de gnubg. */
export interface MoveAnalysis {
/** Nombre de coups légaux. */
readonly moveCount: number;
/** Place du coup joué dans le classement, à partir de 1. */
readonly rank: number;
readonly played: EvaluatedMove;
readonly best: EvaluatedMove;
/** Équité du coup joué moins celle du meilleur : 0 ou négative. */
readonly equityLoss: number;
readonly skill: Skill;
}
/** Décision de videau : doubler ou non (joueur au trait), prendre ou passer
* (son adversaire). */
export type CubeAction = "noDouble" | "double" | "take" | "pass";
/** Ce que le moteur dit d'une décision de videau. */
export interface CubeAnalysis {
/** gnubg analyse-t-il cette décision ? Pas quand le joueur au trait ne
* peut pas doubler, ni à la position de départ. */
readonly analysed: boolean;
/** Équités du joueur au trait, normalisées pour un videau de 1 (null si
* non analysée). */
readonly equities: CubeEquities | null;
/** Équité perdue par celui qui décide : 0 ou négative. */
readonly equityLoss: number;
readonly skill: Skill;
}
export interface CubeEquities {
readonly noDouble: number;
readonly doubleTake: number;
readonly doublePass: number;
/** Après les meilleures décisions des deux joueurs. */
readonly optimal: number;
}
/**