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; } } }