Bot Logic & Difficulty
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The Bot Logic system in Dreamcats provides an automated opponent for "Solo vs AI" mode. It is designed to simulate human-like decision-making based on memory tracking, probability, and difficulty-tiered heuristics. The system handles all phases of the game, from the initial peeking of cards to complex special actions like swapping and drawing.
The core implementation resides in src/lib/bot-logic.ts, while the execution loop is managed within the useGame hook. The difficulty system modulates bot behavior by adjusting thresholds for card values, the likelihood of making mistakes, and the aggression of calling "Pobudka" (Wake Up).
Sources: src/lib/bot-logic.ts, src/state/useGame.ts:316-320, RULES.md
Core Architecture
Bot Memory System
Bots utilize a dedicated memory structure to track cards they have seen. Unlike human players who rely on mental memory, the bot logic maintains a BotMemory object for each bot instance.
ownCards: A Map storingcardIndextovaluefor cards in the bot's own hand.lastPeekedOpponentCard: Stores details about cards viewed via special actions.
The memory is managed through helper functions that ensure data is updated whenever a bot peeks at a card or swaps a card in its hand.
Decision Cycle
The bot logic is non-reactive and relies on the useGame hook to trigger a "tick" when it is a bot's turn. The getBotAction function serves as the primary entry point, delegating logic based on the current GamePhase.
decidePeekAction: Selects unpeeked cards during the setup phase.decidePlayAction: Decides whether to draw from the deck, draw from the discard pile, or call "Pobudka".decideHeldCardAction: Evaluates a drawn card to either swap it, discard it, or activate a special power.
Sources: src/lib/bot-logic.ts:251-285, src/state/useGame.ts:413-435
Difficulty Configuration
The game supports three difficulty levels: Easy, Normal, and Hard. These settings adjust the DifficultySettings object, which controls thresholds and probabilities.
Difficulty Parameters
| Parameter | Description |
|---|---|
takeDiscardThreshold | The maximum card value the bot will consider taking from the discard pile. |
takeDiscardChance | Probability that the bot will actually take a card below the threshold. |
useSpecialChance | Probability of activating a special action (Take 2, Peek 1, Swap 2) when drawn. |
callPobudkaChance | A function evaluating known cards and estimated score to trigger the round end. |
mistakeChance | Probability that the bot will make a sub-optimal move (e.g., swapping a low card for a random unknown). |
Sources: src/lib/bot-logic.ts:38-83
Behavior Comparison
- Easy: Lenient threshold (2), high mistake chance (35%), and only calls Pobudka if score is $\leq 6$ and all cards are known.
- Normal: Balanced threshold (3), lower mistake chance (12%), and more aggressive Pobudka logic.
- Hard: Aggressive threshold (3), minimal mistakes (3%), and high Pobudka confidence even with unknown cards.
Sources: src/lib/bot-logic.ts:49-76, src/tests/bot-difficulty.test.ts:25-35
Implementation Logic
Score Estimation
Bots estimate their own score to decide when to call "Pobudka". If a card value is unknown in memory, the bot assumes a default value of 5.
function estimateOwnScore(bot: Player, memory: BotMemory): number {
let total = 0;
for (let i = 0; i < bot.hand.length; i++) {
if (memory.ownCards.has(i)) {
total += memory.ownCards.get(i)!;
} else {
total += 5; // Average assumption
}
}
return total;
}
Sources: src/lib/bot-logic.ts:89-101
Special Action Handling
Bots handle special cards drawn from the deck with specific heuristics:
- Take 2: The bot compares both cards and chooses the lower value.
- Peek 1: High difficulty bots prioritize peeking at opponent cards, while easy bots prioritize their own unknown cards.
- Swap 2: Bots attempt to swap their highest known card (value $\geq 6$) with a random opponent's card.
Sources: src/lib/bot-logic.ts:182-205, src/lib/bot-logic.ts:219-245
Execution Loop in useGame
The processBotTurns function in useGame.ts manages the timing of bot actions. It uses setTimeout to create a natural delay (approx. 350ms per action) and prevents runaway loops using a MAX_STEPS cap of 15 actions per turn cycle.
Summary
The bot logic provides a scalable difficulty system by combining deterministic state evaluation (memory-based scoring) with stochastic behavior (chance-based actions). By modulating the mistakeChance and callPobudkaChance, the system effectively simulates different skill levels, from beginners who ignore the discard pile to experts who aggressively manage their hand value and call the round end early.
Sources: src/lib/bot-logic.ts:49-83, RULES.md:Section 6