# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview A hockey match engine simulation built with PhaserJS and TypeScript. The engine uses continuous positioning (exact X/Y coordinates on a 2D rink) combined with behavior trees for AI decision-making to create a realistic hockey match simulation. **Core Concept**: Players have exact positions on a 60x30m international hockey rink, with AI running behavior trees at 60 FPS to make tactical decisions (passing, shooting, positioning, etc.). ## Development Commands ```bash # Start development server (runs on port 3000) pnpm run dev # Build for production pnpm run build # Preview production build pnpm run preview ``` ## Coordinate System **Critical**: The rink uses a centered coordinate system: - Origin (0, 0) = center of rink - Rink dimensions: 60m length Ɨ 30m width - Left goal: x = -26m, Right goal: x = +26m - All positions use **meters as floats** (not integers) - Screen rendering: 1 meter = 20 pixels (SCALE constant) ## Architecture ### Project Structure ``` src/ config/ constants.ts # All game constants (rink dimensions, colors, speeds, AI parameters) game/ main.ts # Phaser game initialization and config GameScene.ts # Main game scene (rendering, game loop, physics, event handling) Goal.ts # Goal structure with physics bodies and scoring detection entities/ Player.ts # Player entity with physics, movement, and detection systems Puck.ts # Puck entity with physics and state management systems/ BehaviorTree.ts # Main behavior tree system for AI decision-making BehaviorNodes.ts # Base classes (Selector, Sequence, Condition, Action) behaviors/ SkaterBehavior.ts # Top-level skater AI (context selector) GoalieBehavior.ts # Goalie-specific AI TransitionBehavior.ts # Loose puck / neutral zone behavior offensive/ PuckCarrierBehavior.ts # Shoot/carry/evade decisions OffensiveSupportBehavior.ts # Support when teammate has puck (planned) defensive/ DefensiveBehavior.ts # Chase and pressure opponent types/ game.ts # TypeScript types and interfaces utils/ coordinates.ts # Game ↔ screen coordinate conversion math.ts # Distance, angle utilities ``` ### Implementation Status **āœ“ Completed Phases:** - **Phase 1**: Environment setup, rink rendering - **Phase 2**: Player entities with smooth acceleration/deceleration and rotation - **Phase 3**: Puck physics and possession mechanics - **Phase 4**: Puck carrier behavior (shoot/carry/evade) - **Phase 6**: Basic defensive behavior (chase puck carrier) - **Phase 7**: Basic goalie AI (track puck position) - **Phase 8**: Goal detection, scoring system, pause-aware reset timers **🚧 In Progress / Partial:** - **Phase 5**: Offensive support (placeholder only) - Tackle mechanics (implemented but needs tuning) - Puck reception (implemented with skill-based probability) **šŸ“‹ Planned:** - Passing AI (identify and execute passes) - Advanced offensive positioning (heat maps, formations) - Faceoffs and game flow states - Save mechanics for goalies --- ## Core Systems Documentation ### 1. Behavior Tree System **Location:** [src/systems/BehaviorTree.ts](src/systems/BehaviorTree.ts), [src/systems/BehaviorNodes.ts](src/systems/BehaviorNodes.ts) **Purpose:** AI decision-making engine that runs at 60 FPS for each player. **Architecture:** - **BehaviorNode**: Abstract base class for all nodes - **Selector**: OR logic - tries children until one succeeds - **Sequence**: AND logic - all children must succeed - **Condition**: Boolean predicate functions - **Action**: Leaf nodes that return PlayerAction **Decision Tree Structure:** ``` Root Selector ā”œā”€ Goalie? → GoalieBehavior └─ Skater? → SkaterBehavior ā”œā”€ Has puck? → PuckCarrierBehavior (shoot/carry/evade) ā”œā”€ Teammate has puck? → OffensiveSupportBehavior (planned) ā”œā”€ Opponent has puck? → DefensiveBehavior (chase) └─ Loose puck → TransitionBehavior (chase loose puck) ``` **Key Files:** - [BehaviorTree.ts:26-60](src/systems/BehaviorTree.ts#L26-L60): Main tree evaluation - [SkaterBehavior.ts:21-39](src/systems/behaviors/SkaterBehavior.ts#L21-L39): Context-based selector --- ### 2. Player Entity System **Location:** [src/entities/Player.ts](src/entities/Player.ts) **Purpose:** Player physics, movement, rotation, and nearby player detection. **Key Features:** **Movement System** ([Player.ts:186-286](src/entities/Player.ts#L186-L286)): - Smooth acceleration with ease-out curve (PLAYER_ACCELERATION) - Speed-dependent rotation (faster = wider turns) - Deceleration when near target or after goals - Stop threshold to prevent jittering (MOVEMENT_STOP_THRESHOLD) **Player Detection System** ([Player.ts:324-387](src/entities/Player.ts#L324-L387)): - Physics-based circular sensor (NEAR_PLAYER_DETECTION_RADIUS = 4m) - Field-of-view filtering (NEAR_PLAYER_DETECTION_ANGLE = 180°) - Maintains sets: `nearbyPlayers`, `nearbyOpponents`, `nearbyTeammates` - Methods: `getDetectedOpponents()`, `getDetectedTeammates()` **Tackle System** ([Player.ts:290-312](src/entities/Player.ts#L290-L312)): - Cooldown timer (TACKLE_COOLDOWN = 1000ms) - Fall duration when tackled (TACKLE_FALL_DURATION = 500ms) - Speed requirement (TACKLE_MIN_SPEED = 2 m/s) - Angle-based effectiveness modifiers **Player Attributes** ([types/game.ts:27-33](src/types/game.ts#L27-L33)): - `speed`: Movement speed (0-100) → m/s via SPEED_SCALE_FACTOR - `skill`: Pass/shot accuracy, decision quality - `tackling`: Tackle success probability - `balance`: Resist being tackled - `handling`: Puck reception and control --- ### 3. Puck Entity System **Location:** [src/entities/Puck.ts](src/entities/Puck.ts) **Purpose:** Puck physics, state management, and possession tracking. **Puck States** ([types/game.ts:22](src/types/game.ts#L22)): - `loose`: Free on ice, physics-driven - `carried`: Held by player (carrier ID tracked) - `passing`: In flight between players (future) - `shot`: Shot toward goal **Physics Configuration** ([Puck.ts:36-56](src/entities/Puck.ts#L36-L56)): - Circular collision body (PUCK_RADIUS = 0.2m) - Max velocity: MAX_PUCK_VELOCITY = 50 m/s - Drag (ice friction): PUCK_DRAG = 200 pixels/s² - Bounce coefficient: PUCK_BOUNCE = 0.6 (loses energy) - World bounds collision enabled **Key Methods:** - `setCarrier(playerId, team)`: Assign possession - `setLoose()`: Release to physics simulation - `update()`: Sync game coordinates with physics body --- ### 4. Puck Carrier Behavior **Location:** [src/systems/behaviors/offensive/PuckCarrierBehavior.ts](src/systems/behaviors/offensive/PuckCarrierBehavior.ts) **Purpose:** Tactical decisions when player has possession. **Decision Priority:** 1. **Evade** if opponent threatens head-on ([PuckCarrierBehavior.ts:104-254](src/systems/behaviors/offensive/PuckCarrierBehavior.ts#L104-L254)) 2. **Shoot** if good opportunity ([PuckCarrierBehavior.ts:262-308](src/systems/behaviors/offensive/PuckCarrierBehavior.ts#L262-L308)) 3. **Carry** toward opponent's net (default) **Evasion System:** - Uses physics-based player detection (NEAR_PLAYER_DETECTION_RADIUS) - Checks if opponent is within 60° of goal direction - Maintains consistent evasion direction per opponent (stored in `activeEvasions` map) - Evasion angle: ±60° (EVASION_ANGLE) from goal direction - Clears evasion when opponent leaves detection zone **Shooting Logic:** - Must be in front of goal (not behind) - Distance ≤ SHOOTING_RANGE (10m) - Angle-based accuracy: - Close range (≤3m): 120° shooting angle allowed - Normal range: 60° shooting angle required - Aims at center of net (targetY = 0) **Debug Visualization** (when DEBUG = true): - Green line to goal - Red circle around threats being evaded - Yellow arrow showing evasion direction - Orange circles for detected opponents --- ### 5. GameScene System **Location:** [src/game/GameScene.ts](src/game/GameScene.ts) **Purpose:** Main game loop, physics management, collision detection, event handling. **Key Responsibilities:** **Physics Setup:** - Player-player collisions (including tackle mechanics) - Player-puck overlaps (pickup and reception) - Puck-goal post collisions with bounce - Detection sensor overlaps (nearby player tracking) **Puck Management:** - Carrier positioning: puck stays 1m in front of carrier - Pickup radius: PUCK_PICKUP_RADIUS = 1.5m - Reception skill checks (PUCK_RECEPTION_BASE_CHANCE) - Speed-based reception difficulty **Shooting System:** - Shot speed: SHOT_SPEED = 30 m/s (or 0.6Ɨ for close range) - Post bounce: reduces speed and adds random angle variation - Goal detection via overlap with scoring zone **Tackle System:** - Cooldown enforcement (TACKLE_COOLDOWN) - Angle-based effectiveness (head-on = 100%, side = 70%, etc.) - Closing speed modifiers - Puck loose probability (TACKLE_PUCK_LOOSE_CHANCE = 60%) **Goal System:** - Freeze game on goal event - 3-second pause-aware timer - Player deceleration (GOAL_DECELERATION_RATE) - Reset positions to center ice --- ### 6. Coordinate System **Location:** [src/utils/coordinates.ts](src/utils/coordinates.ts) **Purpose:** Convert between game coordinates (meters) and screen coordinates (pixels). **Critical Details:** - **Game coordinates:** Origin (0, 0) at center of rink, meters as floats - **Screen coordinates:** Origin at top-left, pixels - **Scale factor:** 1 meter = 20 pixels (SCALE constant) - **Y-axis inversion:** Game Y increases upward, screen Y increases downward **Key Methods:** - `gameToScreen(scene, gameX, gameY)`: Meters → pixels - `screenToGame(scene, screenX, screenY)`: Pixels → meters - `getScreenCenter(scene)`: Canvas center in pixels **Rink Layout:** - Rink: 60m Ɨ 30m - Left goal: x = -26m (GOAL_LINE_OFFSET) - Right goal: x = +26m - Blue lines: x = ±9m (BLUE_LINE_OFFSET) - Center ice: (0, 0) --- ### 7. Constants Configuration **Location:** [src/config/constants.ts](src/config/constants.ts) **Purpose:** Centralized configuration for all game parameters. **Categories:** **Game Settings:** - DEBUG, FPS, UI_BOTTOM_PADDING **Rink Dimensions:** - RINK_LENGTH, RINK_WIDTH, SCALE, corner radius, zone lines **Player Constants:** - Radius (goalie vs skater), rotation speed, acceleration/deceleration - Speed scale factor, movement threshold **Puck Constants:** - Radius, pickup range, carry distance, max velocity - Drag, bounce, shot speed, reception parameters **AI/Behavior:** - Shooting range and angle thresholds (normal vs close-range) - Goalie range, detection radius and angle - Evasion angle **Tackle Mechanics:** - Success modifiers, cooldown, fall duration - Angle thresholds and modifiers - Closing speed thresholds **Collision/Physics:** - Post bounce reduction, puck loose chance - Reception skill scaling --- ## Type Definitions **Location:** [src/types/game.ts](src/types/game.ts) **Key Types:** ```typescript PlayerPosition: 'LW' | 'C' | 'RW' | 'LD' | 'RD' | 'G' TeamSide: 'home' | 'away' PlayerState: 'offensive' | 'defensive' PuckState: 'loose' | 'carried' | 'passing' | 'shot' PlayerAttributes: { speed, skill, tackling, balance, handling } GameState: { puck: Puck allPlayers: Player[] } PlayerAction: { type: 'move' | 'chase_puck' | 'skate_with_puck' | 'shoot' | 'idle' targetX?, targetY? } ``` --- ## Technical Stack - **Framework**: Phaser 3.90.0 (Arcade Physics engine) - **TypeScript**: Strict mode enabled - **Build Tool**: Vite 5.4 - **Target FPS**: 60 (configured in constants.ts) - **Physics**: Arcade physics with zero gravity (top-down view) - **Coordinate System**: Centered origin (0,0), meters as float values - **Rendering Scale**: 1 meter = 20 pixels --- ## Debug Features **Toggle:** Set `DEBUG = true` in [constants.ts](src/config/constants.ts) **Visual Overlays:** - **Player movement:** Line and marker showing target position - **Player detection:** Magenta wedge showing field-of-view sensor - **Puck carrier evasion:** - Green line to goal - Red circles around detected threats - Yellow/green arrows showing evasion direction - Orange circles for all nearby opponents **Console Logging:** - Goal events with team and goal location - Shot attempts with player ID - Tackle results and success calculations --- ## Development Workflow **Hot Reload Development:** ```bash pnpm run dev # Starts on localhost:3000 with hot reload ``` **Testing Approach:** - Test each subsystem incrementally before integration - Use DEBUG mode to visualize AI decision-making - Tune constants based on gameplay feel (see [constants.ts](src/config/constants.ts)) - Validate physics with edge cases (goal posts, rink boundaries) **Key Tuning Parameters:** - Player acceleration/deceleration curves → smooth movement feel - Detection radius/angle → evasion responsiveness - Shooting angles → goal frequency balance - Tackle modifiers → physical gameplay intensity - Puck drag/bounce → realistic puck physics **Documentation:** - **[PLAN.md](PLAN.md)**: Phase-by-phase implementation plan - **[NOTES.md](NOTES.md)**: Architecture decisions and design rationale - **[REVIEW.md](REVIEW.md)**: Progress reviews and lessons learned - **[CLAUDE.md](CLAUDE.md)** (this file): System reference for AI assistant --- ## Implementation Patterns **Adding New Behaviors:** 1. Create behavior class extending `BehaviorNode` in `src/systems/behaviors/` 2. Implement `tick(player, gameState)` method 3. Add to appropriate selector in `SkaterBehavior` or `GoalieBehavior` 4. Test in isolation before integration **Adding New Constants:** 1. Add to appropriate section in [constants.ts](src/config/constants.ts) 2. Use semantic names (e.g., `SHOOTING_RANGE` not `MAX_DIST`) 3. Include units in comments (meters, m/s, radians, pixels) 4. Export for use across codebase **Physics Bodies:** - Players: Circular bodies (radius varies by position) - Puck: Circular body with drag and bounce - Goals: Static rectangular bodies for posts/bars - Sensors: Physics zones with `overlap` not `collide` **Coordinate Conversions:** - Always use `CoordinateUtils.gameToScreen()` and `screenToGame()` - Never mix coordinate systems in calculations - Store positions in game coordinates (meters), convert for rendering