## ADDED Requirements ### Requirement: Deck creation and shuffling The game engine SHALL create a standard 52-card deck and shuffle it using a random algorithm before each hand. #### Scenario: Full 52-card deck created - **WHEN** a new deck is initialized - **THEN** the deck contains exactly 52 cards covering all ranks (2 through Ace) across all four suits #### Scenario: Deck is shuffled randomly - **WHEN** a deck is prepared for dealing - **THEN** the card order is randomized and differs between consecutive shuffles ### Requirement: Dealing phase execution The game engine SHALL deal 2 hole cards to each active player, then burn and deal community cards at each street (flop, turn, river). #### Scenario: Hole cards dealt to all players - **WHEN** a hand begins dealing - **THEN** each active player receives exactly 2 face-down hole cards #### Scenario: Flop deals 3 community cards - **WHEN** the pre-flop betting round completes - **THEN** 3 community cards are dealt face-up to the board #### Scenario: Turn deals 1 community card - **WHEN** the flop betting round completes - **THEN** 1 additional community card is dealt face-up #### Scenario: River deals final community card - **WHEN** the turn betting round completes - **THEN** 1 final community card is dealt face-up ### Requirement: Betting round progression The game engine SHALL progress through four betting rounds (pre-flop, flop, turn, river) in sequence, each starting after the player left of the dealer. #### Scenario: Pre-flop begins first - **WHEN** hole cards are dealt - **THEN** the pre-flop betting round starts with the player left of the dealer button #### Scenario: Flop follows pre-flop - **WHEN** all active players have matched bets in the pre-flop round - **THEN** community cards (flop) are dealt and the flop betting round begins #### Scenario: Showdown after river - **WHEN** the river betting round completes with 2+ active players remaining - **THEN** a showdown is triggered where remaining hole cards are revealed ### Requirement: Blind posting The game engine SHALL enforce small blind and big blind posting before each hand, positioned left of the dealer button. #### Scenario: Small blind posted - **WHEN** a new hand starts - **THEN** the player immediately left of the dealer posts the small blind amount #### Scenario: Big blind posted - **WHEN** a new hand starts - **THEN** the player two seats left of the dealer posts the big blind amount (2x small blind) ### Requirement: Player action validation The game engine SHALL validate each player action against the current game state and reject invalid actions. #### Scenario: Fold rejected when no bet to call - **WHEN** a player attempts to fold but no preceding bet exists in the current round - **THEN** the action is rejected and Check is suggested instead #### Scenario: Raise amount validated - **WHEN** a player attempts to raise - **THEN** the raise amount must be at least the size of the previous bet or big blind, whichever is larger #### Scenario: All-in limited by chip count - **WHEN** a player goes all-in with fewer chips than the call amount - **THEN** the player's entire stack is posted and they are marked as all-in ### Requirement: Hand evaluation and winner determination The game engine SHALL evaluate each remaining player's best 5-card hand from their 2 hole cards and 5 community cards, then award the pot to the winner. #### Scenario: Best hand wins the pot - **WHEN** showdown occurs with multiple active players - **THEN** the player with the highest-ranking poker hand wins the entire pot #### Scenario: Split pot on tie - **WHEN** two or more players have hands of equal rank at showdown - **THEN** the pot is divided equally among tied players #### Scenario: Last player standing wins without showdown - **WHEN** all opponents fold leaving one active player - **THEN** that player wins the pot without a showdown and hole cards are not revealed ### Requirement: Pure function state transitions The game engine SHALL represent each action as a pure function that takes the current `GameState` and returns a new immutable `GameState`. #### Scenario: State immutability preserved - **WHEN** an action function is called with a game state - **THEN** the original state object is unchanged and a new state object is returned ### Requirement: Bot turn decision execution **WHEN** it is a bot player's turn to act **THEN** the system SHALL invoke the bot decision engine (base strategy → personality filter → skill noise) to compute the action, execute the action through the existing action application functions, and advance the turn to the next active player #### Scenario: Bot makes personality-driven decision - **WHEN** it is a TAG bot's turn with a medium-strength hand in late position - **THEN** the bot raises according to TAG personality profile rather than making a random choice #### Scenario: Bot decision respects timer constraints - **WHEN** timer is enabled and it is a bot's turn - **THEN** the bot makes its decision within the configured timer duration, with decision time recorded for observation tracking ### Requirement: PlayerSeat type includes personality data The system SHALL extend the PlayerSeat type to include `personality` (bot archetype enum) and `skillLevel` (skill tier enum) fields. Human players SHALL have these fields set to null or a default human value. Existing fields (id, name, chips, currentBet, betMatched, status, holeCards, position) SHALL remain unchanged. #### Scenario: Bot seat includes personality data - **WHEN** a bot player is created with LAG archetype at Hard skill - **THEN** the PlayerSeat object has personality: "LAG" and skillLevel: "Hard" #### Scenario: Human seat has no bot personality - **WHEN** the human player's PlayerSeat is created - **THEN** personality and skillLevel fields are null or marked as human ### Requirement: GameState tracks observation data The system SHALL extend the GameState to include an `observationData` field containing per-player tracked statistics (VPIP, PFR, Fold-to-CBet, WTSD, bet sizing profiles, timing data). Observation data SHALL update after each completed hand and SHALL persist across hands within a session. #### Scenario: Observation data accumulates across hands - **WHEN** 10 hands have been played and observation tracking is active - **THEN** GameState.observationData contains accumulated statistics for all bot players