Veit F. bcb5465247 feat: implement foundational poker table with game engine and UI
Add complete Texas Hold'em poker gameplay including:
- Pure function game engine (deck, dealing, betting, showdown)
- Hand evaluator supporting all 10 poker hand ranks
- Animated card components with 3D flip transitions
- CSS Grid oval poker table layout for up to 9 seats
- Player seat components with chip tracking and turn indicators
- Bet controls with conditional button visibility
- Basic AI opponents with random valid action selection
- Turn advancement, all-in auto-advance, and dealer rotation

Sync delta specs to main specs: poker-table, card-components,
game-engine, player-state.
2026-05-17 17:28:38 +02:00

63 lines
4.1 KiB
Markdown

## Context
Fresh SvelteKit 2 + Svelte 5 project with no poker functionality. The proposal defines four capabilities: poker table UI, card components, game engine, and player state management. No external dependencies will be added — everything uses Svelte 5 runes, native CSS, and built-in transition primitives.
## Goals / Non-Goals
**Goals:**
- Playable Texas Hold'em game with human player vs AI opponents
- Smooth card flip/deal animations using Svelte's `flip()` and `transition:` directives
- Clean component hierarchy with clear separation between UI components and game logic
- Responsive poker table layout that works on desktop screens
- State management via Svelte 5 runes (`$state`, `$derived`) — no stores needed
**Non-Goals:**
- Multiplayer networking (local play only)
- Tournament mode or cash game buy-in flows
- Educational tools, strategy guidance, or GTO analysis
- TailwindCSS or any CSS framework — native Svelte styling only
- Mobile-first responsive design (desktop first)
## Decisions
### State Management: Runes over Stores
Using Svelte 5 `$state` and `$derived` runes instead of writable stores. The game state is a single reactive object passed down through component props. This avoids the store subscription overhead and gives us true two-way binding with `$stateful` when needed for form inputs.
**Alternatives considered:** Svelte stores (legacy pattern, unnecessary complexity), Zustand or external state library (adds dependency, defeats purpose of using Svelte 5 runes).
### Game Engine: Pure Functions over Classes
The game engine will be a set of pure functions operating on an immutable `GameState` object. Each action (deal, bet, fold, check) returns a new state. This makes the logic testable, predictable, and easy to reason about. The UI layer reads from this state and dispatches actions.
**Alternatives considered:** Class-based engine (mutable state, harder to test), finite state machine library (overhead for a single game type).
### Card Animations: Svelte `flip()` + CSS 3D Transforms
Card flip uses CSS `transform: rotateY(180deg)` with `backface-visibility: hidden`. Dealing animations use Svelte's `flip()` spring animation to animate cards from dealer position to their final seat. Hover effects use simple CSS transitions on scoped styles.
**Alternatives considered:** Framer Motion or motion library (external dependency), SVG-based cards (unnecessary complexity).
### Table Layout: CSS Grid
The poker table uses a single CSS Grid with named areas for each player seat, community card zone, and pot display. Seat positions are calculated using `grid-column`/`grid-row` based on an oval table shape. The dealer button rotates using grid positioning updates driven by `$derived` state.
**Alternatives considered:** Absolute positioning (hard to maintain), Flexbox-only layout (insufficient for radial seating arrangement).
### Project Structure
```
src/lib/
types/ # TypeScript interfaces (Card, Hand, Player, GameState)
game/ # Pure game logic functions (deck, betting, hand evaluation)
components/ # Svelte UI components (Card, PokerTable, PlayerSeat, BetControls)
utils/ # Helpers (hand ranker, suit/rank constants)
```
## Risks / Trade-offs
- **Hand evaluation algorithm complexity** → Using a simplified scoring approach (rank-based comparison) rather than enumerating all 7-card combinations. May miss edge cases in rare hands but keeps implementation manageable for v1.
- **No external animation library** → Svelte's `flip()` handles most cases, but complex multi-card deal sequences may require manual spring configuration. Acceptable trade-off for zero dependencies.
- **Single-page game only** → No route-based navigation; entire game lives on the root page. This simplifies state management but means no browser back-button support mid-game.
## Open Questions
- How many AI difficulty levels should the initial engine support? (Suggested: one basic level with random valid actions)
- Should blinds be configurable or fixed for v1? (Suggested: fixed small/big blind, configurable via game state)
- What chip denomination system to use? (Suggested: simple numeric values, no visual chip denominations needed in v1)