using System;
using System.Collections.Generic;
namespace MazeGen
{
///
/// Tracks one agent's progress through the maze: current room, ordered path history
/// (for visualization/backtracking), and O(1) sets for "have I been here" / "have I
/// used this exit" checks. Plain C# class - no MonoBehaviour/scene dependency, so it's
/// cheap to run many of these (e.g. for future autonomous multi-agent scenarios).
///
/// Also tracks the agent's combat state (character sheet, health, equipment).
///
public class MazeAgent
{
public readonly string Name;
public Room CurrentRoom { get; private set; }
public int NewRoomsVisited { get; private set; }
public bool IsFinished { get; private set; }
/// The exit the agent walked through to reach CurrentRoom, if any (null for the starting room). Used by AutonomousAgentBrain to avoid immediately reversing.
public Exit LastUsedExit { get; private set; }
/// This agent's character sheet (stats, equipment, inventory).
public CharacterSheet CharacterSheet { get; private set; }
/// Track if this agent died (different from IsFinished, which means reached the exit).
public bool IsDead => !CharacterSheet.Stats.IsAlive;
private readonly List _path = new List();
private readonly HashSet _visitedRoomIds = new HashSet();
private readonly HashSet _usedExitIds = new HashSet();
private readonly Dictionary _visitCounts = new Dictionary();
public IReadOnlyList PathHistory => _path;
public event Action RoomEntered;
public event Action ReachedExitRoom;
public event Action Died;
public MazeAgent(string name, Room startRoom, CharacterSheet characterSheet = null)
{
Name = name;
CharacterSheet = characterSheet ?? new CharacterSheet(new CharacterStats());
EnterRoom(startRoom, null);
}
public bool HasVisited(int roomId) => _visitedRoomIds.Contains(roomId);
public bool HasUsedExit(Exit exit) => _usedExitIds.Contains(exit.Id);
/// How many times this agent has personally entered the given room (0 if never).
public int VisitCount(int roomId) => _visitCounts.TryGetValue(roomId, out var count) ? count : 0;
public void EnterRoom(Room room, Exit viaExit)
{
// Check if agent is already dead before entering
if (IsDead)
return;
if (viaExit != null)
_usedExitIds.Add(viaExit.Id);
if (_visitedRoomIds.Add(room.Id))
NewRoomsVisited++;
_visitCounts[room.Id] = VisitCount(room.Id) + 1;
CurrentRoom = room;
LastUsedExit = viaExit;
_path.Add(room);
RoomEntered?.Invoke(room);
if (room.Kind == RoomKind.Exit)
{
IsFinished = true;
ReachedExitRoom?.Invoke(room);
}
}
/// Called when the agent dies (defeated in combat or other hazard). Stops them from moving.
public void Die()
{
if (IsDead) return;
CharacterSheet.Stats.CurrentHealth = 0;
Died?.Invoke();
}
}
}