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

4.1 KiB

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)