Vampire-Act-Base/docs/architecture/adr-005.md

85 lines
3.4 KiB
Markdown

# ADR-005: Enemy AI Decision Model
**Status**: Accepted
**Date**: 2026-04-27
**Engine**: Unity 2022.3.62f3c1
**GDD Requirements Addressed**: Enemy AI Logic, Boss AI Logic (systems-index.md #4, #5)
---
## Context
Nightborn's enemy AI doesn't need complex tactical reasoning, but has a special requirement: each enemy type must strongly favor a specific form, creating "I need to switch" pressure. MVP scope is 3-5 enemy types. The AI model must be simple to implement, produce predictable behavior, and be easily understood and tested by external developers.
## Decision
**Use lightweight per-type Finite State Machines. Reject Behavior Trees and Utility AI.**
### Base FSM Structure (shared by all enemy types)
```
Idle ──→ Chase ──→ Attack ──→ Cooldown
↑ │ │
└────────────────────┴──────────┘
If too far, return to Chase
```
### Per-Type Differentiation in the Attack State
| Enemy Type | Attack Behavior | Encouraged Form | Why |
|------------|----------------|-----------------|-----|
| **Swarm** | Many simultaneous small-area hits | Mist | Mist's circular AOE clears groups at once |
| **Brute** | Slow, high-damage single strike | Human | Human's parry window is clear and precise against it |
| **Stalker** | Fast rush + point-blank flurry | Wolf | Wolf's rectangular dash collides for a stagger counter |
| **Shooter** | Ranged projectile barrage from periphery | Mist/Wolf | Mist phases through to close, or Wolf bursts to eliminate |
| **Boss** | Multi-phase mixed patterns | All forms | Phase transitions require form adaptation |
### Why Not Behavior Trees
BTs excel at complex decision chains (e.g., FPS cover-shooter AI). Nightborn enemies need only 4 states. The tree's maintenance cost exceeds its value.
### Why Not Utility AI
Scoring systems produce "optimal" behavior but aren't predictable enough — players can't learn enemy patterns, violating the "Battlefield is Information" pillar.
### Implementation
```csharp
// L0 — Pure C#, returns one AICommand per frame
public enum EnemyStateType { Idle, Chase, Attack, Cooldown }
public class EnemyAILogic
{
public EnemyTypeConfig Config;
public AICommand ComputeAction(EnemyState self, PlayerState player)
{
TransitionState(self, player);
return CurrentState switch
{
Idle => ScanForPlayer(player),
Chase => MoveToward(player),
Attack => ExecuteAttack(self.AttackPattern, player),
Cooldown => WaitAndReset(self.CooldownTimer),
};
}
// Per-type override for unique transition logic
protected virtual void TransitionState(EnemyState self, PlayerState player) { }
}
```
### Boss Extension
Boss AI extends the base FSM with:
- `BossPhase` enum (additional state dimension)
- Phase transition conditions (health thresholds, timer triggers)
- `OnPhaseChanged` event for L1 VFX/Audio synchronization
## Consequences
- External developers can understand an enemy's behavior from `EnemyTypeConfig` alone — no need to parse behavior trees
- Enemy behavior is predictable and learnable — satisfies "Battlefield is Information" pillar
- Each enemy type's Attack pattern naturally points to one form counter — reinforces "Form is Tactics"
- If future enemies need more intelligence (cover, coordination), the FSM base can be extended without replacement