- Separate base behavior nodes into BehaviorNodes.ts (fixes circular dependency) - Organize behaviors by role (goalie) and context (offensive/defensive/transition) - Add modular behavior subtrees: - GoalieBehavior: Track puck position near net - SkaterBehavior: Route to context-specific behaviors - PuckCarrierBehavior: Shoot/carry logic (Phase 4) - OffensiveSupportBehavior: Placeholder for Phase 5 - DefensiveBehavior: Placeholder for Phase 6 - TransitionBehavior: Chase loose puck - Maintain backward compatibility with static evaluatePlayer() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import type { Player } from '../entities/Player';
|
|
import type { GameState, PlayerAction } from '../types/game';
|
|
import { BehaviorNode, Selector, Sequence, Condition } from './BehaviorNodes';
|
|
import { GoalieBehavior } from './behaviors/GoalieBehavior';
|
|
import { SkaterBehavior } from './behaviors/SkaterBehavior';
|
|
|
|
// Re-export base classes for convenience
|
|
export { BehaviorNode, BehaviorStatus, Selector, Sequence, Condition, Action } from './BehaviorNodes';
|
|
|
|
/**
|
|
* BehaviorTree system for AI decision-making
|
|
*
|
|
* This system uses a behavior tree pattern to make tactical decisions for players.
|
|
* The tree is evaluated every tick (60 FPS) and produces actions based on:
|
|
* - Game state (possession, positions, threats)
|
|
* - Player attributes (Hockey IQ, Skill, Speed)
|
|
* - Tactical context (offensive/defensive situation)
|
|
*
|
|
* The tree is structured by role (goalie vs skater) at the top level,
|
|
* then by game context (offensive/defensive/transition) for skaters.
|
|
*
|
|
* @example
|
|
* const tree = new BehaviorTree(player);
|
|
* const action = tree.tick(gameState); // Called every frame in GameScene.update()
|
|
*/
|
|
export class BehaviorTree {
|
|
private root: BehaviorNode;
|
|
|
|
constructor(private player: Player) {
|
|
// Root selector: Choose between goalie and skater behaviors based on position
|
|
this.root = new Selector([
|
|
// Goalie behavior (checks position internally)
|
|
new Sequence([
|
|
new Condition((p) => p.playerPosition === 'G'),
|
|
new GoalieBehavior()
|
|
]),
|
|
// Skater behavior (default for all other positions)
|
|
new SkaterBehavior()
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Evaluates the behavior tree and returns the next action for the player
|
|
* Called every frame (60 FPS)
|
|
*/
|
|
public tick(gameState: GameState): PlayerAction {
|
|
const result = this.root.tick(this.player, gameState);
|
|
// Result should always be a PlayerAction from our structure
|
|
return result as PlayerAction;
|
|
}
|
|
|
|
/**
|
|
* Static helper to evaluate any player
|
|
* This maintains backward compatibility with existing code
|
|
*/
|
|
public static evaluatePlayer(player: Player, gameState: GameState): PlayerAction {
|
|
const tree = new BehaviorTree(player);
|
|
return tree.tick(gameState);
|
|
}
|
|
}
|