Game State Reducer
Relevant source files
The following files were used as context for generating this wiki page:
The Game State Reducer logic in Dreamcats is primarily encapsulated within the Convex backend mutations, specifically the performAction mutation. This system handles the transition of the game state based on player actions, ensuring that rules are enforced and state remains synchronized across all clients. The reducer processes various game phases—from initial peeking to card swapping and special action execution—while maintaining data integrity through idempotency keys.
Sources: convex/actions.ts:13-25, src/state/types.ts:33-45
Core Architecture and Data Flow
The state management follows a unidirectional flow where client-side components dispatch actions via the broadcastAction utility, which invokes the performAction mutation on the Convex backend. The backend validates the action against the current gamePhase and player turn before updating the database.
State Synchronization Flow
The following diagram illustrates the sequence of a typical game action, such as drawing a card, and how the state is reduced and synchronized.
The reducer is responsible for verifying that it is the correct player's turn (isMyTurn) and that the gamePhase permits the requested action.
Sources: convex/actions.ts:79-130, src/components/Gameboard.tsx:210-220
Game Phases and Transition Logic
The reducer operates as a finite state machine, transitioning the gamePhase based on the outcome of actions and the completion of sub-tasks (like special card effects).
| Phase | Purpose | Trigger Action | Next Phase |
|---|---|---|---|
lobby | Players joining | START_NEW_ROUND | peeking |
peeking | Initial 2-card look | FINISH_PEEKING | playing |
playing | Main turn loop | DRAW_FROM_DECK/DISCARD | holding_card |
holding_card | Deciding card use | SWAP_HELD_CARD / USE_SPECIAL_ACTION | playing / action_* |
action_take_2 | Draw 2 keep 1 | ACTION_TAKE_2_CHOOSE | holding_card |
round_end | Scoring reveal | START_NEW_ROUND | peeking |
Sources: convex/tests/rooms-and-games.test.ts:40-52, convex/actions.ts:250-350
Phase Transition Diagram
This flowchart depicts the logic within the reducer for advancing phases during a standard gameplay loop.
Action Handlers and Logic
Turn Advancement
The reducer uses a helper function, advanceTurn, to rotate the currentPlayerIndex. This function increments the turnCount, resets drawnCard and drawSource buffers, and sets the phase back to playing.
Sources: convex/actions.ts:133-145
Scoring and "Pobudka" Logic
The endRoundWithScores reducer logic calculates the final sums for each player. It specifically handles:
- Caller's Risk: If the player who called "Pobudka" does not have the strictly lowest score, they receive a +5 penalty.
- Game Over Condition: If any player's cumulative score reaches 100, the phase transitions to
game_over.
// Example of penalty logic in the reducer
const lastRoundScores = scores.map((entry) => {
let penalty = 0;
if (options.reason === "pobudka" && options.callerId &&
entry.player.id === options.callerId && !callerHasLowest) {
penalty = 5;
}
return { playerId: entry.player.id, score: entry.score, penalty };
});
Sources: convex/actions.ts:150-200, convex/tests/rooms-and-games.test.ts:182-240
Special Action Implementation
Special card actions interrupt the normal turn flow by branching into specific action phases:
- Take 2: Moves 2 cards from
drawPiletotempCards. The player must choose one to keep, which returns them to theholding_cardphase. - Swap 2: A two-step selection process (
action_swap_2_select_1andaction_swap_2_select_2) where the reducer validates target player IDs and card indices before performing an array swap in the player hand data.
Sources: convex/actions.ts:400-480, src/components/GameActions.tsx:100-120
Technical Implementation Details
The reducer logic utilizes several data structures to manage complex state transitions:
- Idempotency: Every mutation can be accompanied by an
idempotencyKey. The reducer checks themovestable to prevent double-applying state changes if a client retries a request. - Validation: The reducer validates card counts (e.g., ensuring a player only peeks at exactly 2 cards during the
peekingphase as per Rule §3). - Side Effects: Mutations include "side effects" like recording match results in the
matchesanduserStatstables when agame_overtransition occurs.
Sources: convex/actions.ts:25-50, convex/actions.ts:89-125, convex/actions.ts:260-280
Conclusion
The Game State Reducer is the central authority for gameplay integrity in Dreamcats. By centralizing logic in Convex mutations, the project ensures that complex rules—such as scoring penalties and special card sequences—are executed consistently. Its design as a phase-driven state machine allows for clear transitions between different stages of the game while maintaining a high level of technical robustness through idempotency and reactive updates.