| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- namespace MazeGen
- {
- /// <summary>
- /// 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)
- /// }
- /// </summary>
- public class AgentDecisionTree
- {
- private List<AgentDecision> _decisions = new List<AgentDecision>();
- 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;
- /// <summary>
- /// 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.
- /// </summary>
- 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;
- }
- /// <summary>
- /// Evaluate just the preconditions without executing or thinking.
- /// Useful for debugging or logging what decisions are available.
- /// </summary>
- public AgentDecision FindApplicableDecision(MazeAgent agent)
- {
- foreach (var decision in _decisions)
- {
- if (decision.CanExecute(agent))
- return decision;
- }
- return null;
- }
- /// <summary>
- /// Get the list of all decisions that could currently execute.
- /// </summary>
- public List<AgentDecision> GetAvailableDecisions(MazeAgent agent)
- {
- var available = new List<AgentDecision>();
- foreach (var decision in _decisions)
- {
- if (decision.CanExecute(agent))
- available.Add(decision);
- }
- return available;
- }
- }
- }
|