using System;
using System.Collections.Generic;
using UnityEngine;
namespace MazeGen
{
///
/// Manages a prioritized list of agent decisions. On each call, iterates through decisions
/// in order, finds the first one that CanExecute(), and calls both Execute() and Think()
/// in lockstep so behavior and narration stay synchronized.
///
/// Usage pattern:
/// var tree = new AgentDecisionTree();
/// tree.Add(new HandleExistingFightDecision(director));
/// tree.Add(new DeclareFightDecision(director));
/// tree.Add(new SneakAwayDecision(director));
/// tree.Add(new MoveOnDecision(generator));
///
/// // In your update loop:
/// if (!tree.TryDecide(agent)) {
/// // No decision could execute (shouldn't happen if the last decision is a catch-all)
/// }
///
public class AgentDecisionTree
{
private List _decisions = new List();
public void Add(AgentDecision decision)
{
if (decision == null)
throw new ArgumentNullException(nameof(decision));
_decisions.Add(decision);
}
public void Insert(int index, AgentDecision decision)
{
if (decision == null)
throw new ArgumentNullException(nameof(decision));
_decisions.Insert(index, decision);
}
public void Remove(AgentDecision decision) => _decisions.Remove(decision);
public void RemoveAt(int index) => _decisions.RemoveAt(index);
public int Count => _decisions.Count;
///
/// Evaluate the decision tree: find the first decision that can execute, then Execute it.
/// If Execute returns true, call Think to narrate it.
/// Returns true if a decision was executed, false if none could execute.
///
public bool TryDecide(MazeAgent agent)
{
if (agent == null) return false;
foreach (var decision in _decisions)
{
if (!decision.CanExecute(agent))
continue;
// This decision can execute - do it
bool consumed = decision.Execute(agent);
if (consumed)
{
// Narrate the decision
decision.Think(agent);
return true;
}
}
// No decision could execute
return false;
}
///
/// Evaluate just the preconditions without executing or thinking.
/// Useful for debugging or logging what decisions are available.
///
public AgentDecision FindApplicableDecision(MazeAgent agent)
{
foreach (var decision in _decisions)
{
if (decision.CanExecute(agent))
return decision;
}
return null;
}
///
/// Get the list of all decisions that could currently execute.
///
public List GetAvailableDecisions(MazeAgent agent)
{
var available = new List();
foreach (var decision in _decisions)
{
if (decision.CanExecute(agent))
available.Add(decision);
}
return available;
}
}
}