# BPC_AIMemorySystem — AI Memory System

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- **Requires:** [`BB_AgentBoard`](BB_AgentBoard.md) — Writes `InvestigateLocation`, `bIsInvestigating` keys
- **Requires:** [`BPC_AIPerceptionSystem`](BPC_AIPerceptionSystem.md) — Receives sight/sound/damage stimuli
- **Required By:** [`AI_BaseAgentController`](AI_BaseAgentController.md) — Uses memory for investigation decisions
- **Engine/Plugin Requirements:** AI Module, GameplayTags

### Purpose
Gives AI agents persistent short-term memory: where they last saw the player, what sounds they heard, which areas they've searched. Prevents AI from "forgetting" the player immediately on breaking line of sight and avoids re-searching already investigated locations.

---

## 1. Enums

```text
Enum Name: E_MemoryType
(DisplayName = "Memory Type")

Values:
  Sighting       = 0    // Visual detection of target
  Sound          = 1    // Heard noise/audio event
  Damage         = 2    // Received damage
  Smell          = 3    // Olfactory detection (future/optional)
  ScriptedHint   = 4    // Designer-placed hint (scripted memory injection)
```

---

## 2. Structs

### `S_AIMemoryEntry`
| Field | Type | Description |
|-------|------|-------------|
| `Location` | Vector | World position of the memory |
| `MemoryType` | E_MemoryType | What triggered this memory |
| `Timestamp` | Float | Game time when memory was recorded |
| `Confidence` | Float | 0.0–1.0 confidence in this memory (sighting = 1.0, sound = variable) |

---

## 3. Variables

### Configuration (Instance Editable, Expose On Spawn)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `MemoryDecayTime` | Float | 30.0 | MemoryConfig | Seconds before a memory expires and is removed |
| `MaxMemoryEntries` | Integer | 20 | MemoryConfig | Maximum concurrent memory entries |
| `SearchRadius` | Float | 500.0 | MemoryConfig | Min distance between searched locations to consider them distinct |

### Internal (Private / Protected, No Expose)

| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `MemoryEntries` | Array of S_AIMemoryEntry | Empty | Internal | All active timestamped memory records |
| `SearchedLocations` | Array of Vector | Empty | Internal | World positions already investigated |

---

## 4. Functions

### Public Functions

#### `AddMemoryEntry` → `void`
- **Description:** Records a new memory entry from perception stimulus.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Location` | Vector | World position of event |
  | `MemoryType` | E_MemoryType | What kind of stimulus |
  | `Confidence` | Float | How certain the memory is (0.0–1.0) |
- **Blueprint Authority:** Any
- **Flow:** Create S_AIMemoryEntry → populate fields → append to MemoryEntries → trim if over MaxMemoryEntries → broadcast OnMemoryAdded

#### `GetLatestMemoryOfType` → `S_AIMemoryEntry`
- **Description:** Returns the most recent memory entry of a specific type. Returns empty/invalid entry if none found.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `MemoryType` | E_MemoryType | Filter by type |
- **Blueprint Authority:** Any

#### `GetAllRecentMemories` → `Array of S_AIMemoryEntry`
- **Description:** Returns all non-expired memory entries sorted by timestamp (newest first).
- **Parameters:** None
- **Blueprint Authority:** Any

#### `HasSearchedLocation` → `Bool`
- **Description:** Checks if a location (within SearchRadius) has already been investigated.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Location` | Vector | World position to check |
- **Blueprint Authority:** Any

#### `MarkLocationSearched` → `void`
- **Description:** Records a location as having been searched.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `Location` | Vector | World position searched |
- **Blueprint Authority:** Any
- **Flow:** Add Location to SearchedLocations → push InvestigateLocation to blackboard if more memories exist

#### `ClearMemories` → `void`
- **Description:** Wipes all memory entries and searched locations. Called on alert reset or agent death.
- **Parameters:** None
- **Blueprint Authority:** Any

#### `TickMemoryDecay` → `void`
- **Description:** Called on tick to remove expired memories based on MemoryDecayTime.
- **Parameters:**
  | Param | Type | Description |
  |-------|------|-------------|
  | `DeltaTime` | Float | Frame delta time |
- **Flow:** Iterate MemoryEntries → remove those where `(CurrentTime - Timestamp) > MemoryDecayTime`

---

## 5. Event Dispatchers

| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnMemoryAdded` | Entry: S_AIMemoryEntry | Public | New memory recorded |
| `OnMemoryExpired` | Entry: S_AIMemoryEntry | Public | Memory decayed and removed |
| `OnLocationSearched` | Location: Vector | Public | Location marked as searched |
| `OnAllLocationsSearched` | — | Public | No more unsearched memory locations remain |

---

## 6. Overridden Events / Custom Events

### Event: `ReceivePerceptionStimulus`
- **Description:** Subscribes to [`BPC_AIPerceptionSystem`](BPC_AIPerceptionSystem.md) dispatchers on BeginPlay. Routes sight, sound, and damage events to memory.
- **Flow:**
  1. On sighting: AddMemoryEntry(Location, Sighting, 1.0)
  2. On sound: AddMemoryEntry(Location, Sound, 0.5–0.9 based on distance)
  3. On damage: AddMemoryEntry(InstigatorLocation, Damage, 1.0)
  4. Write InvestigateLocation to blackboard if not already investigating

---

## 7. Blueprint Graph Logic Flow

```mermaid
flowchart TD
    A[BeginPlay] --> B[Subscribe to Perception dispatchers]
    B --> C[Idle]
    C --> D{Perception event received?}
    D --> E[Create S_AIMemoryEntry]
    E --> F[Add to MemoryEntries]
    F --> G{MemoryEntries count >= Max?}
    G -->|Yes| H[Remove oldest entry]
    G -->|No| I[Broadcast OnMemoryAdded]
    H --> I
    I --> J{Agent not investigating?}
    J -->|Yes| K[Write InvestigateLocation to BB]
    J -->|No| L[Skip — already busy]
    K --> L
    L --> C

    subgraph Tick
        M[TickMemoryDecay] --> N{Entry expired?}
        N -->|Yes| O[Broadcast OnMemoryExpired]
        N -->|No| P[Keep entry]
        O --> Q[Remove from MemoryEntries]
    end
```

---

## 8. Communication Matrix

| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| [`BPC_AIPerceptionSystem`](BPC_AIPerceptionSystem.md) | Dispatcher | Sighting: Location+Confidence, Sound: Location+Volume, Damage: InstigatorLocation |
| [`BB_AgentBoard`](BB_AgentBoard.md) | Blackboard write | `InvestigateLocation`, `bIsInvestigating` |
| [`AI_BaseAgentController`](AI_BaseAgentController.md) | Direct (owns) | Tick calls for memory decay |
| Behaviour Tree (`BT_Investigate`) | Direct read | `GetLatestMemoryOfType`, `HasSearchedLocation` |
| [`BPC_EncounterDirector`](../10-adaptive/BPC_ProceduralEncounter.md) | Direct read | Memory entries for encounter escalation decisions |

---

## 9. Validation / Testing Checklist

- [ ] E_MemoryType enum has all 5 values defined
- [ ] S_AIMemoryEntry struct has 4 fields (Location, MemoryType, Timestamp, Confidence)
- [ ] AddMemoryEntry correctly appends and trims to MaxMemoryEntries
- [ ] GetLatestMemoryOfType returns newest entry filtered by type
- [ ] HasSearchedLocation returns true for locations within SearchRadius of a searched point
- [ ] TickMemoryDecay correctly removes entries older than MemoryDecayTime
- [ ] ClearMemories wipes both MemoryEntries and SearchedLocations
- [ ] Edge case: no memories of requested type returns empty struct
- [ ] Edge case: memory decay on empty array does nothing
- [ ] Edge case: rapid perception events don't overflow (MaxMemoryEntries cap works)

---

## 10. Reuse Notes

- MemoryDecayTime can be tuned per archetype (patrol guards forget quickly, stalker remembers longer)
- SearchedLocations prevents AI from repeatedly checking the same hiding spot
- Confidence parameter supports fuzzy memory: sounds at edge of range have lower confidence, AI may not act on low-confidence memories
- Memory system is independent of behaviour tree logic — BT reads from memory API to make decisions
- For co-op/multiplayer, add a shared memory blackboard for squad-level memory

---

*Specification based on Master Section 10.4, line 3012.*