import type { AIPlayer, AIPlayerContext, } from '../AIPlayer'; import { shouldActivateFlipperBase } from '../AIPlayer'; import type { AIDifficulty, AIDifficultyParams, AIPersonality, SetupConfig, } from '../../types'; // DefensiveAI — «Бэтти-Защитница». // Стратегия: цепкая защита, бустер только на cradle (не реализовано в Phase 1-2). // Setup: 2 slingshot в углах ворот, 1 турбо рядом, 1 вираж в дальнем углу, 1 пустой. // см. ~/Knowledge/Projects/pinball-duel/concepts/bot-ai-design.md#1-defensive-«бэтти-защитница» export class DefensiveAI implements AIPlayer { readonly personality: AIPersonality = 'defensive'; readonly difficulty: AIDifficulty; readonly params: AIDifficultyParams; private lastReactionTimeLeft = 0; private lastReactionTimeRight = 0; constructor(difficulty: AIDifficulty, params: AIDifficultyParams) { this.difficulty = difficulty; this.params = params; } update(ctx: AIPlayerContext): void { // Defensive — реагирует надёжно на любой приближающийся мяч const shouldLeft = shouldActivateFlipperBase( ctx, 'left', this.params, this.lastReactionTimeLeft, this.difficulty, ); if (shouldLeft) { if (ctx.leftFlipper.activate()) { this.lastReactionTimeLeft = performance.now(); } } const shouldRight = shouldActivateFlipperBase( ctx, 'right', this.params, this.lastReactionTimeRight, this.difficulty, ); if (shouldRight) { if (ctx.rightFlipper.activate()) { this.lastReactionTimeRight = performance.now(); } } } generateSetup(): SetupConfig { // см. bot-ai-design.md#defensive-setup-эвристика return { slots: [ { slotId: 'goal_corner_left', bumperType: 'slingshot' }, { slotId: 'goal_corner_right', bumperType: 'slingshot' }, { slotId: 'near_goal_center', bumperType: 'turbo' }, { slotId: 'mid_left', bumperType: 'curve' }, { slotId: 'mid_right', bumperType: null }, // 1 пустой слот ], }; } destroy(): void { // No state to clean } }