Play With Bot Mode
Overview
Section titled “Overview”Play With Bot mode allows users to play a full offline game of Dice Chess against a local bot. The bot can run two distinct heuristics:
- Greedy Bot: Prioritizes capturing material or delivering mate.
- Random Bot: Chooses random valid sequences of moves based on the rolled dice values.
The game flows according to the core Dice Chess domain rules: a player rolls 3 dice at the start of a turn, then has up to 3 micro-moves to consume those dice before transitioning control to the opponent.
Architectural Layout
Section titled “Architectural Layout”To ensure maintainability, the module is divided into a high-cohesion, composed architecture under src/lib/playWithBot/. A slim orchestrator store coordinates user events and delegates core duties to dedicated reactive sub-systems.
graph TD
Store["PlayWithBotStore (Orchestrator)"] -->|Composes| History["PlayWithBotHistory"]
Store -->|Composes| Dice["PlayWithBotDice"]
Store -->|Delegates to| Bot["PlayWithBotBot (AI Service)"]
Sub-System Responsibilities
Section titled “Sub-System Responsibilities”1. PlayWithBotStore (Coordinator)
Section titled “1. PlayWithBotStore (Coordinator)”The primary entry point and orchestrator for the game mode.
- State (
$state):gameStatus(idle,rolling,playing,bot_thinking,victory,defeat),playerColor,botAlgorithm,activeColor, andpendingPromotion. - Duties: Coordinates page/view entry, manages timed transitions, plays sound effects, saves local game summaries to IndexedDB via
saveLocalGame, and exposes backward-compatible delegating properties to the UI.
2. PlayWithBotHistory (History & Navigation)
Section titled “2. PlayWithBotHistory (History & Navigation)”Tracks game progress, moves, and supports interactive move navigation.
- State (
$state):historyMap(associates move index to position states),currentMoveIndex,maxMoveIndex,turnHistory, andcurrentTurnRecord. - Derived (
$derived):historyBlocks: Organizes individual micro-moves into clear, turn-by-turn visual groupings.canGoToStart/canGoToEnd: State checks for disabling/enabling navigation buttons in the UI.
- Duties: Logs valid moves, registers new positions, and allows step-by-step navigation through the played game.
3. PlayWithBotDice (Dice Pool Manager)
Section titled “3. PlayWithBotDice (Dice Pool Manager)”Maintains the state of the active turn’s dice pool.
- State (
$state):currentDice(array ofDieStateobjects containing value, allowed, and used flags) andisAnimatingRoll. - Derived (
$derived):availableDiceValues(computes values of dice that are allowed and have not yet been used in the active turn). - Duties: Generates random dice pools, triggers rolling animations, and encapsulates usage mutations through
markUsedandrevertUsemethods.
4. PlayWithBotBot (Stateless AI Service)
Section titled “4. PlayWithBotBot (Stateless AI Service)”Isolates greedy and random algorithm move selection.
- State: Stateless.
- Duties: Interfaces asynchronously with the
@rabestro/dicechess-engineviaselectBestMove(fen, diceValues, algorithm). It formats inputs as standard DFEN strings and retrieves optimized move series. - Injectability: Features test-injections
setBotDiceChessInstanceandresetBotDiceChessInstanceto seamlessly support mocked engine instances in test environments.
Reactivity & Svelte 5 Runes
Section titled “Reactivity & Svelte 5 Runes”The module utilizes Svelte 5 Runes to maintain perfect reactive synchronization between UI components and decoupled store states:
$state: Keeps fields likecurrentDice,historyMap, andcurrentMoveIndexdeeply reactive.$derived/$derived.by: Automatically recomputes the UI board’slegalMovesDestsandhistoryBlocksas soon as the active dice pool or move position changes.$state.snapshot: Used in history state recording (dices: $state.snapshot(this.currentDice)) to capture frozen values of reactive proxies, preventing reactive leakage into historic blocks.
Testing & Test Isolation
Section titled “Testing & Test Isolation”By separating history, dice, and bot AI into discrete modules, we are able to perform robust, isolated testing:
playWithBotHistory.test.ts: Verifies starting position initialization, turn history logging, and correct visualhistoryBlocksgrouping.playWithBotDice.test.ts: Exercises dice generation bounds (e.g., uppercase piece codes for White, lowercase for Black), animation states, and encapsulation flags.playWithBotBot.test.ts: Simulates Greedy/Random heuristic recommendations and handles engine errors gracefully.playWithBotStore.bot.test.ts: Tests bot integrations, turn transitions, victory/defeat statuses, and timeout delays.
All unit tests are run via Vitest in frontend PWA, maintaining a 100% green execution rate.
Advanced Gameplay Mechanics
Section titled “Advanced Gameplay Mechanics”To match the @rabestro/dicechess-engine 1.2.0 capabilities, several high-fidelity gameplay features are integrated into the store:
1. Bidirectional Draw Offers
Section titled “1. Bidirectional Draw Offers”Draws can be negotiated between the human player and the AI bot:
- Player-Initiated Draws: The player can offer a draw during their turn when
gameStatusis'playing'. The bot evaluates the position asynchronously using the engine’sshouldBotAcceptDrawfunction to decide the outcome. - Bot-Initiated Draws: Before rolling dice on its turn, the bot evaluates the board state. If the engine’s
shouldBotOfferDrawfunction returns true, the bot pauses its turn and shows a dedicated overlay modal for the player to accept or decline. - State Management: Tracked via
playerCanOfferDraw,botCanOfferDraw, andactiveDrawOffer('player' | 'bot' | null).
2. Player Resignation
Section titled “2. Player Resignation”- The player can resign at any time during active play. Resigning instantly concludes the game with a
'defeat'status for the player. - The bot is strictly configured to never resign.
3. Timer & Race Condition Safeguards
Section titled “3. Timer & Race Condition Safeguards”- Timer Pausing: To prevent time exploits, the active game timer is paused (
this.stopTimer()) when a draw offer is pending. It resumes (this.startTimer()) if the player declines the bot’s draw offer. - Race Condition Prevention: The async 1.2-second bot thinking delay in
offerDraw()is protected by validating thatthis.startTime(the unique game session identifier) hasn’t changed. If the player resets or starts a new game during the delay, the draw offer is discarded without mutating the new session state.
4. Betting & Balance Integration
Section titled “4. Betting & Balance Integration”- When starting a game with a configured bet amount (
bet > 0), the player’s balance is verified and debited. - Upon game conclusion, payouts are resolved:
- Victory: The player receives double their bet (
2 * bet). - Draw: The player is refunded their original bet (
bet). - Defeat: The player forfeits the wagered bet.
- Victory: The player receives double their bet (
Key Files
Section titled “Key Files”frontend-pwa/src/lib/playWithBot/playWithBotStore.svelte.ts— The primary coordinating store.frontend-pwa/src/lib/playWithBot/playWithBotHistory.svelte.ts— Game navigation and turn record-keeping.frontend-pwa/src/lib/playWithBot/playWithBotDice.svelte.ts— Dice pool, states, and roll generators.frontend-pwa/src/lib/playWithBot/playWithBotBot.ts— AI bot move calculations.frontend-pwa/src/lib/playWithBot/index.ts— Consolidated module exports.