From 4bf182c2a9ee3e8092fe784f17077fec8f4092d3 Mon Sep 17 00:00:00 2001 From: Pierre Wessman <4029607+pierrewessman@users.noreply.github.com> Date: Fri, 19 Sep 2025 10:48:24 +0200 Subject: [PATCH] remove energy mechanism --- .claude/settings.local.json | 4 +- PLAYER-AI.md | 319 ------------------------------------ src/engine/game-engine.js | 1 - src/entities/player.js | 25 +-- src/systems/debug-system.js | 7 - src/systems/renderer.js | 13 +- 6 files changed, 6 insertions(+), 363 deletions(-) delete mode 100644 PLAYER-AI.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json index e74c0d5..4b519cb 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -2,7 +2,9 @@ "permissions": { "allow": [ "Bash(find:*)", - "Bash(node:*)" + "Bash(node:*)", + "Bash(git add:*)", + "Bash(git commit:*)" ], "deny": [], "ask": [] diff --git a/PLAYER-AI.md b/PLAYER-AI.md deleted file mode 100644 index 4818af8..0000000 --- a/PLAYER-AI.md +++ /dev/null @@ -1,319 +0,0 @@ -# Player AI System Documentation - -This document provides a comprehensive overview of the AI decision-making system for hockey players in the game, including detailed flowcharts showing how player states and behaviors are determined. - -## Overview - -The Player AI system uses a sophisticated Entity-Component-System (ECS) pattern with context-aware decision making. Each player has multiple layers of state management: - -- **Physical State**: Position, velocity, energy, puck possession -- **AI State**: Current behavior, target, reaction timing -- **Game Context**: Team possession, puck location, game situation - -## Core AI Decision Flow - -```mermaid -flowchart TD - A[Player Update Called] --> B{Is Goalie?} - B -->|Yes| C[Update Goalie AI] - B -->|No| D[Check Reaction Time] - D --> E{Reaction Time Met?} - E -->|No| F[Skip AI Update] - E -->|Yes| G{Is Faceoff Active?} - G -->|Yes| H[Handle Faceoff Positioning] - G -->|No| I[Determine Puck Possession] - I --> J{Who Has Puck?} - J -->|My Team| K[Team Has Puck Behavior] - J -->|Opponent Team| L[Opponent Has Puck Behavior] - J -->|Loose Puck| M[Loose Puck Behavior] - - C --> N[Position in Crease] - H --> O[Move to Faceoff Position] - K --> P[Offensive Strategy] - L --> Q[Defensive Strategy] - M --> R[Puck Competition] - - F --> S[End Update] - N --> S - O --> S - P --> S - Q --> S - R --> S -``` - -## Team Possession States - -### When Team Has Puck - -```mermaid -flowchart TD - A[Team Has Puck] --> B{Do I Have Puck?} - B -->|Yes| C[Offensive Behavior With Puck] - B -->|No| D[Support Offensive Behavior] - - C --> E{Distance to Goal < 250?} - E -->|Yes| F{Good Shooting Angle?} - F -->|Yes| G{Distance < 150 OR Random < 0.5?} - G -->|Yes| H[SHOOT] - G -->|No| I[Consider Pass] - F -->|No| I - E -->|No| I - - I --> J{Teammate Closer to Goal?} - J -->|Yes| K{Random < 0.7?} - K -->|Yes| L[PASS to Closer Teammate] - K -->|No| M[Check Pressure] - J -->|No| M - - M --> N{Opponent Distance < 100?} - N -->|Yes| O{Find Good Pass Target?} - O -->|Yes| P{Random < 0.8?} - P -->|Yes| Q[PASS to Best Target] - P -->|No| R[ADVANCE to Goal] - O -->|No| R - N -->|No| R - - D --> S[Calculate Support Position] - S --> T[Move to Support Position] - - H --> U[End Turn] - L --> U - Q --> U - R --> U - T --> U -``` - -### When Opponent Has Puck - -```mermaid -flowchart TD - A[Opponent Has Puck] --> B{Am I Closest Defender?} - B -->|Yes| C[Aggressive Pressure] - B -->|No| D[Defensive Positioning] - - C --> E[Target Puck Carrier] - C --> F[Set Behavior: aggressive_pressure] - - D --> G[Calculate Defend Position] - D --> H[Set Behavior: defending] - - E --> I[End Turn] - F --> I - G --> I - H --> I -``` - -### When Puck is Loose - -```mermaid -flowchart TD - A[Puck is Loose] --> B{Am I Closest to Puck?} - B -->|Yes| C{Distance < 200?} - C -->|Yes| D[Chase Puck] - C -->|No| E[Formation Position] - B -->|No| E - - D --> F[Set Behavior: chasing] - E --> G[Calculate Formation Position] - E --> H[Set Behavior: formation] - - F --> I[End Turn] - G --> I - H --> I -``` - -## Formation System - -### Team State Determination - -```mermaid -flowchart TD - A[Determine Team State] --> B{Does Teammate Have Puck?} - B -->|Yes| C[ATTACKING] - B -->|No| D{Does Opponent Have Puck?} - D -->|Yes| E[DEFENDING] - D -->|No| F[Check Puck Location] - - F --> G{Team Side} - G -->|Home| H{Puck X > 67% Width?} - G -->|Away| I{Puck X < 33% Width?} - - H -->|Yes| C - H -->|No| E - I -->|Yes| C - I -->|No| E -``` - -### Position Calculation by Role - -```mermaid -flowchart TD - A[Calculate Position] --> B{Team State} - B -->|Attacking| C[Attacking Formation] - B -->|Defending| D[Defending Formation] - - C --> E{Player Role} - E -->|Center| F[Attack Zone, Center Y] - E -->|Left Wing| G[Attack Zone - 50, Center Y - 120] - E -->|Right Wing| H[Attack Zone - 50, Center Y + 120] - E -->|Left Defense| I[Attack Zone - 150, Center Y - 80] - E -->|Right Defense| J[Attack Zone - 150, Center Y + 80] - - D --> K{Player Role} - K -->|Center| L[Defense Zone, Center Y] - K -->|Left Wing| M[Defense Zone + Side*50, Center Y - 100] - K -->|Right Wing| N[Defense Zone + Side*50, Center Y + 100] - K -->|Left Defense| O[Defense Zone + Side*100, Center Y - 60] - K -->|Right Defense| P[Defense Zone + Side*100, Center Y + 60] - - F --> Q[Apply Puck Influence] - G --> Q - H --> Q - I --> Q - J --> Q - L --> Q - M --> Q - N --> Q - O --> Q - P --> Q - - Q --> R[Clamp to Rink Bounds] - R --> S[Final Position] -``` - -## Decision Making Algorithms - -### Pass Target Selection - -```mermaid -flowchart TD - A[Find Best Pass Target] --> B[Loop Through Teammates] - B --> C{Distance 50-300?} - C -->|No| D[Skip Teammate] - C -->|Yes| E[Check Pass Blocking] - - E --> F[Loop Through Opponents] - F --> G{Opponent Blocks Pass Line?} - G -->|Yes| H[Mark as Blocked] - G -->|No| I[Continue Check] - - I --> J{More Opponents?} - J -->|Yes| F - J -->|No| K{Pass Blocked?} - - K -->|Yes| D - K -->|No| L[Calculate Score] - L --> M[Score = Skill / Distance] - M --> N{Best Score So Far?} - N -->|Yes| O[Update Best Target] - N -->|No| P[Continue] - - D --> Q{More Teammates?} - P --> Q - O --> Q - Q -->|Yes| B - Q -->|No| R[Return Best Target] - - H --> D -``` - -### Shooting Decision - -```mermaid -flowchart TD - A[Check Shooting Angle] --> B[Calculate Direction to Goal] - B --> C[Loop Through Opponents] - C --> D{Opponent Distance < 150?} - D -->|No| E[Skip Opponent] - D -->|Yes| F[Calculate Direction to Opponent] - F --> G[Calculate Dot Product] - G --> H{Dot > 0.8 AND Distance < 80?} - H -->|Yes| I[Shot Blocked] - H -->|No| J{More Opponents?} - - E --> J - J -->|Yes| C - J -->|No| K[Clear Shot] - - I --> L[Return False] - K --> M[Return True] -``` - -## Goalie AI System - -```mermaid -flowchart TD - A[Goalie Update] --> B[Calculate Goal Position] - B --> C[Define Crease Area] - C --> D{Puck Distance < 80?} - D -->|Yes| E[Aggressive Position] - D -->|No| F[Standard Position] - - E --> G[Lerp Between Puck and Goal (0.3)] - F --> H[Goal + Offset Based on Puck Y] - - G --> I[Clamp to Crease Bounds] - H --> I - I --> J[Set Target Position] -``` - -## Faceoff Positioning - -```mermaid -flowchart TD - A[Faceoff Active] --> B{Player Role} - B -->|Center| C[Position at Faceoff Dot] - B -->|Left Wing| D[Outside Circle + Buffer, Left Side] - B -->|Right Wing| E[Outside Circle + Buffer, Right Side] - B -->|Left Defense| F[Well Outside, Left Side] - B -->|Right Defense| G[Well Outside, Right Side] - B -->|Goalie| H[Stay in Net] - - C --> I[Set as Faceoff Participant] - D --> J[Legal Position Outside Circle] - E --> J - F --> J - G --> J - H --> J - - I --> K[Set Behavior: faceoff] - J --> K -``` - -## AI Behavior States - -The AI system uses several behavior states to track what each player is currently doing: - -- **`aggressive_pressure`**: Actively pursuing the puck carrier -- **`defending`**: Positioning defensively between opponent and goal -- **`chasing`**: Moving directly toward loose puck -- **`formation`**: Moving to calculated formation position -- **`offensive_support`**: Supporting teammate with puck -- **`checking`**: Performing body check on opponent -- **`faceoff`**: Positioned for faceoff situation - -## Key AI Features - -### Reaction Time System -- Each player has a unique reaction time (50-150ms) -- Prevents all players from reacting simultaneously -- Creates more realistic, staggered decision making - -### Energy Management -- Energy affects maximum speed -- Players with low energy (< 20) move 30% slower -- Energy recovers when moving slowly -- Creates realistic fatigue simulation - -### Contextual Decision Making -- Decisions based on multiple factors: distance, player attributes, game situation -- Probabilistic choices add unpredictability -- Different strategies for different scenarios - -### Formation Intelligence -- Dynamic formations based on puck possession -- Role-specific positioning (forwards vs defensemen) -- Puck influence affects positioning slightly -- Maintains team structure while allowing individual decisions - -This AI system creates realistic hockey gameplay with players that react intelligently to game situations while maintaining team strategy and individual characteristics. \ No newline at end of file diff --git a/src/engine/game-engine.js b/src/engine/game-engine.js index 7b75640..77e42ad 100644 --- a/src/engine/game-engine.js +++ b/src/engine/game-engine.js @@ -289,7 +289,6 @@ class GameEngine { player.position = player.homePosition.copy(); player.velocity = new Vector2(0, 0); player.state.hasPuck = false; - player.state.energy = 100; player.aiState.lastAction = 0; }); diff --git a/src/entities/player.js b/src/entities/player.js index 473d460..2a43053 100644 --- a/src/entities/player.js +++ b/src/entities/player.js @@ -35,7 +35,6 @@ class Player { this.state = { hasPuck: false, - energy: 100, checking: false, injured: false }; @@ -53,14 +52,13 @@ class Player { } /** - * Main update loop for the player - handles energy, movement, rotation, and AI behavior + * Main update loop for the player - handles movement, rotation, and AI behavior * @param {number} deltaTime - Time elapsed since last frame in seconds * @param {Object} gameState - Current game state including rink dimensions and game status * @param {Object} puck - Puck object with position and velocity * @param {Array} players - Array of all players on the ice */ update(deltaTime, gameState, puck, players) { - this.updateEnergy(deltaTime); this.updateMovement(deltaTime); this.updateAngle(deltaTime); @@ -71,24 +69,6 @@ class Player { } } - /** - * Updates player energy/stamina based on movement and provides recovery when stationary - * Energy affects max speed - tired players move slower - * @param {number} deltaTime - Time elapsed since last frame in seconds - */ - updateEnergy(deltaTime) { - const energyDrain = this.velocity.magnitude() / this.maxSpeed * 10 * deltaTime; - this.state.energy = Math.max(0, this.state.energy - energyDrain); - - if (this.state.energy < 20) { - this.maxSpeed *= 0.7; - } - - if (this.velocity.magnitude() < 50) { - this.state.energy = Math.min(100, this.state.energy + 15 * deltaTime); - } - } - /** * Updates player physics including movement toward target, velocity limits, and collision bounds * Applies acceleration toward target position with deceleration when close @@ -106,8 +86,7 @@ class Player { this.velocity = this.velocity.multiply(0.8); } - const speedMultiplier = Math.min(1, this.state.energy / 100); - this.velocity = this.velocity.limit(this.maxSpeed * speedMultiplier); + this.velocity = this.velocity.limit(this.maxSpeed); // Reduced friction for more responsive movement this.velocity = Physics.applyFriction(this.velocity, 2, deltaTime); diff --git a/src/systems/debug-system.js b/src/systems/debug-system.js index d494d65..d84e371 100644 --- a/src/systems/debug-system.js +++ b/src/systems/debug-system.js @@ -216,13 +216,11 @@ class DebugSystem { // Update dynamic content only const coordsElement = playerDiv.querySelector('.debug-coords'); const speedElement = playerDiv.querySelector('.debug-speed'); - const energyElement = playerDiv.querySelector('.debug-energy'); const puckElement = playerDiv.querySelector('.debug-puck'); const behaviorElement = playerDiv.querySelector('.debug-behavior'); if (coordsElement) coordsElement.textContent = `Pos: (${player.position.x.toFixed(0)}, ${player.position.y.toFixed(0)})`; if (speedElement) speedElement.textContent = player.velocity.magnitude().toFixed(1); - if (energyElement) energyElement.textContent = `${player.state.energy.toFixed(0)}%`; if (puckElement) puckElement.textContent = player.state.hasPuck; if (behaviorElement) behaviorElement.textContent = player.aiState.behavior; }); @@ -239,7 +237,6 @@ class DebugSystem {
Pos: (${player.position.x.toFixed(0)}, ${player.position.y.toFixed(0)})
Speed: ${player.velocity.magnitude().toFixed(1)}
-
Energy: ${player.state.energy.toFixed(0)}%
Has Puck: ${player.state.hasPuck}
Behavior: ${player.aiState.behavior}
@@ -315,10 +312,6 @@ class DebugSystem { Has Puck: ${player.state.hasPuck} -
- Energy: - ${player.state.energy.toFixed(1)}% -
Checking: ${player.state.checking} diff --git a/src/systems/renderer.js b/src/systems/renderer.js index 03ba832..c6b052e 100644 --- a/src/systems/renderer.js +++ b/src/systems/renderer.js @@ -372,21 +372,10 @@ class Renderer { const x = player.position.x; const y = player.position.y - player.radius - 5; - // Draw player ID and energy + // Draw player ID this.ctx.fillStyle = player.team === 'home' ? '#ff4444' : '#4444ff'; this.ctx.fillText(`${player.role}`, x - 10, y); - // Draw energy bar - const barWidth = 20; - const barHeight = 3; - const energyPercent = player.state.energy / 100; - - this.ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; - this.ctx.fillRect(x - barWidth/2, y - 15, barWidth, barHeight); - - this.ctx.fillStyle = energyPercent > 0.5 ? '#44ff44' : energyPercent > 0.25 ? '#ffff44' : '#ff4444'; - this.ctx.fillRect(x - barWidth/2, y - 15, barWidth * energyPercent, barHeight); - // Highlight puck carrier if (player.state.hasPuck) { this.ctx.strokeStyle = '#ffff00';