Domaine : match, niveau de l'ordinateur, événements en version 2
Partie de match (score et Crawford dits par le moteur), niveau choisi porté par GameStarted, ordinateur joué comme ComputerTurn de gnubg ; migration des journaux de la version 1 ; scénarios, glossaire, ADR 0007 et 0013 amendés. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c0f827c5ba
commit
339d699488
@@ -29,6 +29,7 @@ import { TEXTS } from "./texts.js";
|
||||
/** Les scénarios montrés dans l'aide, dans l'ordre. */
|
||||
export const FEATURES = [
|
||||
"docs/scenarios/jouer-une-partie.feature",
|
||||
"docs/scenarios/jouer-un-match.feature",
|
||||
"docs/scenarios/apprendre-les-regles.feature",
|
||||
"docs/scenarios/mes-parties.feature",
|
||||
"docs/scenarios/partager-une-position.feature",
|
||||
|
||||
@@ -29,6 +29,8 @@ export type Route =
|
||||
| { readonly screen: "games"; readonly game: string | null }
|
||||
/** #/menu. */
|
||||
| { readonly screen: "menu" }
|
||||
/** #/nouvelle-partie : le choix de la partie (type, niveau, conseil). */
|
||||
| { readonly screen: "newGame" }
|
||||
/** #/position/<Position ID>/<Match ID> (Match ID facultatif). */
|
||||
| { readonly screen: "position"; readonly position: string; readonly match: string | null }
|
||||
/** Une adresse que l'application ne connaît pas. */
|
||||
@@ -86,6 +88,8 @@ export function parseRoute(hash: string): Route {
|
||||
return name === null ? { screen: "about" } : unknown;
|
||||
case "menu":
|
||||
return name === null ? { screen: "menu" } : unknown;
|
||||
case "nouvelle-partie":
|
||||
return name === null ? { screen: "newGame" } : unknown;
|
||||
case "parties":
|
||||
return { screen: "games", game: name };
|
||||
case "installer":
|
||||
@@ -166,6 +170,8 @@ export function routeHash(route: Route): string {
|
||||
return route.game === null ? "#/parties" : `#/parties/${route.game}`;
|
||||
case "menu":
|
||||
return "#/menu";
|
||||
case "newGame":
|
||||
return "#/nouvelle-partie";
|
||||
case "position": {
|
||||
const position = `#/position/${encodeURIComponent(route.position)}`;
|
||||
return route.match === null
|
||||
|
||||
+38
-2
@@ -8,6 +8,10 @@
|
||||
// toujours une valeur par défaut, et un réglage enregistré par une version
|
||||
// précédente se relit sans perte.
|
||||
|
||||
import type { NewGame } from "../domain/game/game.js";
|
||||
import { COMPUTER_LEVELS, type ComputerLevel, ENGINE_LEVELS } from "../domain/game/level.js";
|
||||
import { firstGameOf, MATCH_LENGTHS } from "../domain/game/match.js";
|
||||
|
||||
export type Theme = "auto" | "light" | "dark";
|
||||
|
||||
export interface Settings {
|
||||
@@ -34,8 +38,18 @@ export interface Settings {
|
||||
readonly installDismissedAt: number;
|
||||
/** L'application a été installée (événement appinstalled). */
|
||||
readonly installed: boolean;
|
||||
/** Les choix de l'écran « Nouvelle partie », gardés pour la suivante :
|
||||
* partie libre ou match, longueur du match, niveau de l'ordinateur,
|
||||
* conseil du maître. */
|
||||
readonly gameKind: GameKind;
|
||||
readonly matchLength: number;
|
||||
readonly level: ComputerLevel;
|
||||
readonly masterAdvice: boolean;
|
||||
}
|
||||
|
||||
/** Partie libre ou match. */
|
||||
export type GameKind = "free" | "match";
|
||||
|
||||
export const DEFAULT_SETTINGS: Settings = {
|
||||
vibrations: true,
|
||||
keepScreenOn: true,
|
||||
@@ -47,6 +61,10 @@ export const DEFAULT_SETTINGS: Settings = {
|
||||
installDismissals: 0,
|
||||
installDismissedAt: 0,
|
||||
installed: false,
|
||||
gameKind: "free",
|
||||
matchLength: 5,
|
||||
level: "intermediate",
|
||||
masterAdvice: true,
|
||||
};
|
||||
|
||||
/** Nombre de parties pendant lesquelles la consigne garde sa forme longue. */
|
||||
@@ -71,8 +89,9 @@ export function parseSettings(text: string | null): Settings {
|
||||
} catch {
|
||||
// Réglages illisibles : valeurs par défaut.
|
||||
}
|
||||
const bool = (key: "vibrations" | "keepScreenOn" | "welcomed" | "installed") =>
|
||||
typeof raw[key] === "boolean" ? (raw[key] as boolean) : DEFAULT_SETTINGS[key];
|
||||
const bool = (
|
||||
key: "vibrations" | "keepScreenOn" | "welcomed" | "installed" | "masterAdvice",
|
||||
) => (typeof raw[key] === "boolean" ? (raw[key] as boolean) : DEFAULT_SETTINGS[key]);
|
||||
const count = (
|
||||
key:
|
||||
| "gamesStarted"
|
||||
@@ -98,9 +117,26 @@ export function parseSettings(text: string | null): Settings {
|
||||
installDismissals: count("installDismissals"),
|
||||
installDismissedAt: count("installDismissedAt"),
|
||||
installed: bool("installed"),
|
||||
gameKind: raw.gameKind === "match" ? "match" : "free",
|
||||
matchLength: (MATCH_LENGTHS as readonly unknown[]).includes(raw.matchLength)
|
||||
? (raw.matchLength as number)
|
||||
: DEFAULT_SETTINGS.matchLength,
|
||||
level: (COMPUTER_LEVELS as readonly unknown[]).includes(raw.level)
|
||||
? (raw.level as ComputerLevel)
|
||||
: DEFAULT_SETTINGS.level,
|
||||
masterAdvice: bool("masterAdvice"),
|
||||
};
|
||||
}
|
||||
|
||||
/** La partie que lancent les choix de l'écran « Nouvelle partie » : le
|
||||
* niveau de gnubg du niveau choisi, et la première partie d'un match. */
|
||||
export function chosenGame(settings: Settings): NewGame {
|
||||
const level = ENGINE_LEVELS[settings.level];
|
||||
return settings.gameKind === "match"
|
||||
? { level, match: firstGameOf(settings.matchLength) }
|
||||
: { level };
|
||||
}
|
||||
|
||||
/** Le thème suivant, dans l'ordre du menu : automatique, clair, sombre. */
|
||||
export function nextTheme(theme: Theme): Theme {
|
||||
return theme === "auto" ? "light" : theme === "light" ? "dark" : "auto";
|
||||
|
||||
Reference in New Issue
Block a user