┌─────────────────────────────────────────────────────────────────┐
│ MazeAgent (Agent.cs) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ + CurrentRoom: Room │ │
│ │ + IsFinished: bool │ │
│ │ + IsDead: bool │ │
│ │ + CharacterSheet: CharacterSheet ◄──┐ │ │
│ │ + PathHistory: List<Room> │ │ │
│ │ + HasVisited(roomId): bool │ │ │
│ └──────────────────────────────────────┼───────────────────┘ │
│ │ │
└─────────────────────────────────────────┼────────────────────────┘
│
│ owns
▼
┌──────────────────────────────────────────────────────────┐
│ CharacterSheet (CharacterSheet.cs) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ - baseStats: CharacterStats │ │
│ │ - equippedWeapon: Weapon◄──────┐ │ │
│ │ - equippedArmor: Armor◄────┐ │ │ │
│ │ - inventory: List<Item> │ │ │ │
│ │ - tempBonuses: Dict │ │ │ │
│ │ │ │ │ │
│ │ + GetEffectiveAttack() │ │ │ │
│ │ + GetEffectiveDefense() │ │ │ │
│ │ + GetEffectiveSpeed() │ │ │ │
│ │ + EquipWeapon() │ │ │ │
│ │ + EquipArmor() │ │ │ │
│ │ + AddToInventory() │ │ │ │
│ │ + ApplyTemporaryBonus() │ │ │ │
│ └─────────────────────────────────┼───────────────────┘ │
│ │ │
└────────────────────────────────────┼──────────────────────┘
│
┌────────────────┴────────────────┐
│ │
▼ ▼
┌──────────────────────────────┐ ┌──────────────────────────┐
│ CharacterStats │ │ Item (base) │
│ (CharacterStats.cs) │ │ (Items/Item.cs) │
│ ┌────────────────────────┐ │ │ ┌────────────────────┐ │
│ │ - maxHealth │ │ │ │ - itemName │ │
│ │ - speed │ │ │ │ - description │ │
│ │ - attack │ │ │ │ - icon │ │
│ │ - defense │ │ │ │ - rarity │ │
│ │ - magic │ │ │ │ │ │
│ │ - currentHealth │ │ │ │ + OnEquip() │ │
│ │ │ │ │ │ + OnUnequip() │ │
│ │ + Clone() │ │ │ │ + GetLabel() │ │
│ │ + TakeDamage() │ │ │ └────────────────────┘ │
│ │ + IsAlive │ │ │ ▲ │
│ └────────────────────────┘ │ │ │ │
│ │ │ ┌──────┴──────┐ │
└──────────────────────────────┘ │ │ │ │
│ ▼ ▼ │
│ ┌────────┐ ┌────────┐ │
│ │Weapon │ │Armor │ │
│ │(Items/ │ │(Items/ │ │
│ │Weapon) │ │Armor) │ │
│ └────────┘ └────────┘ │
└──────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ Room (Core/Room.cs) │
│ + Encounter: MonsterEncounter ◄──┐ │
│ + Exits: List<Exit> │ │
│ + Position: Vector2 │ │
│ + DepthFromStart: int │ │
└──────────────────────────────────────────────────────────────────────┘
│ has
│
▼
┌──────────────────────────────────────────────────────┐
│ MonsterEncounter (Monsters/MonsterEncounter.cs) │
│ ┌───────────────────────────────────────────────┐ │
│ │ - monsters: List<MonsterInstance> │ │
│ │ - visibleMonsterCount: int (incomplete info) │ │
│ │ │ │
│ │ + SpawnMonsters(templates, min, max) │ │
│ │ + GetPerceivedChallengeRating() │ │
│ │ + GetActualChallengeRating() │ │
│ │ + HasLivingMonsters: bool │ │
│ │ + AliveMonsterCount: int │ │
│ └───────────────────────────────────────────────┘ │
│ │ │
│ │ contains │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ MonsterInstance │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ + Template: Monster │ │ │
│ │ │ + CharacterSheet: CharacterSheet │ │ │
│ │ │ + IsDefeated: bool │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │ │
│ │ uses │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Monster (Monsters/Monster.cs) │ │
│ │ [ScriptableObject Template] │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ + monsterName: string │ │ │
│ │ │ + baseStats: CharacterStats │ │ │
│ │ │ + startingWeapon: Weapon (optional) │ │ │
│ │ │ + startingArmor: Armor (optional) │ │ │
│ │ │ + possibleLoot: Item[] │ │ │
│ │ │ │ │ │
│ │ │ + CreateCharacterSheet() │ │ │
│ │ │ + GetRandomLoot() │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ AutonomousAgentBrain (Agent/AutonomousAgentBrain.cs) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ - _controller: MazeAgentController │ │
│ │ - _retreatThreshold: float │ │
│ │ │ │
│ │ + ChooseExit(agent, room): Exit │ │
│ │ + PeekThroughExit(exit, agent): float [CR] │ │
│ │ + ShouldTakeExit(exit, agent): bool │ │
│ │ + FilterByThreat(exits, agent): List<Exit> │ │
│ │ │ │
│ │ PEEK MECHANIC: │ │
│ │ 1. Before choosing an exit, peek into adjacent rooms │ │
│ │ 2. Get perceived challenge rating (incomplete info) │ │
│ │ 3. Compare to retreat threshold │ │
│ │ 4. Avoid dangerous exits if safer options exist │ │
│ └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ CombatResolver (CombatResolver.cs) [SKELETON - EXPAND ME] │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ + ResolveCombat(agent, encounter): CombatOutcome │ │
│ │ │ │
│ │ - BuildTurnOrder(agent, encounter): List<Turn> │ │
│ │ - ExecuteAgentTurn(agent, encounter) │ │
│ │ - ExecuteMonsterTurn(monster, agent, encounter) │ │
│ │ - AttackMonster(agent, encounter, targetIdx) │ │
│ │ - AttackAgent(monster, agent) │ │
│ │ - AwardLoot(monster, agent) │ │
│ │ │ │
│ │ TODO: Full implementation with: │ │
│ │ - Turn order calculation │ │
│ │ - Multiple damage types │ │
│ │ - Special abilities │ │
│ │ - Status effects │ │
│ │ - AI decision making │ │
│ └──────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
Agent.EnterRoom(room)
└─> room.Encounter exists?
└─> Yes: Trigger combat
└─> CombatResolver.ResolveCombat(agent, encounter)
├─> BuildTurnOrder()
├─> Loop: ExecuteAgentTurn() / ExecuteMonsterTurn()
├─> Return: Victory / Defeat / Fleeing
└─> Apply outcome (agent dies / loot awarded / etc.)
└─> No: Continue normally
AutonomousAgentBrain.ChooseExit()
└─> For each exit:
├─> PeekThroughExit()
│ └─> room.Encounter.GetPerceivedChallengeRating()
└─> ShouldTakeExit()
├─> If CR < retreatThreshold: take it
└─> Else: maybe retreat (randomness)
└─> FilterByThreat() removes dangerous exits
└─> Return safest valid exit
CharacterSheet.EquipWeapon(weapon)
├─> Weapon.OnUnequip() old weapon (if any)
│ └─> RemoveTemporaryBonus()
├─> Weapon.OnEquip(this)
│ └─> ApplyTemporaryBonus("weapon_attack", bonus)
└─> GetEffectiveAttack() now includes bonus
Agent with:
- Base Attack: 10
- Equipped Weapon: +5 Attack bonus
- Temporary Buff: +3 Attack
GetEffectiveAttack() = 10 + 5 + 3 = 18
Defense reduction calculation:
Monster attacks for 20 base damage
Agent defense: 5
Defense reduction: min(10% × 5, 90%) = 50%
Actual damage taken: 20 × (1 - 0.5) = 10
See CombatResolver.cs for where to add these.