using System; using System.Collections.Generic; using UnityEngine; public class CompoundTask : ITask { // ================== Enum Status ========================= public enum DecomposeStatus { None, Failed, Successful } // ================== Variables ========================= private DecomposeStatus decomposeStatus = DecomposeStatus.None; // ================== Properties ========================= public string Name { get; private set; } public bool IsCompound => true; public List<Method> Methods { get; } = new(); public DecomposeStatus Status => decomposeStatus; // ================== DECOMPOSITION ========================= /// <summary> /// Decomposes the CompoundTask into a list of subtasks by checking which Method's preconditions are met. /// </summary> /// <param name="planner">The HTNPlanner used to evaluate the preconditions of each Method.</param> /// <returns> /// A list of ITask subtasks from the first valid Method, /// or null if no Method's preconditions are satisfied. /// </returns> public List<ITask> Decompose(HTNPlanner planner) { foreach (Method method in Methods) { if (method.ArePreconditionsMet(planner)) { decomposeStatus = DecomposeStatus.Successful; Debug.Log($"Added: {method.SubTasks.Count} tasks"); return method.SubTasks; } } decomposeStatus = DecomposeStatus.Failed; return new List<ITask>(); } // ================== ADDING ========================= private void AddMethodInternal(Method method) => Methods.Add(method); //Adds a Method to the CompoundTask /// <summary> /// Adds a Method to the CompoundTask /// </summary> /// <param name="method">The Method object to add to the CompoundTask's Methods list.</param> /// <returns>The current CompoundTask instance (for method chaining).</returns> public CompoundTask AddMethod(Method method) { if (method == null) throw new ArgumentNullException(nameof(method)); AddMethodInternal(method); return this; } /// <summary> /// Adds a List of Methods to the CompoundTask /// </summary> /// <param name="methods">The Method object List to add to the CompoundTask's Methods list.</param> /// <returns>The current CompoundTask instance (for method chaining).</returns> public CompoundTask AddMethod(List<Method> methods) { if (methods == null) throw new ArgumentNullException(nameof(methods)); foreach (Method method in methods) { AddMethodInternal(method); } return this; } /// <summary> /// Finalizes the setup of the CompoundTask by assigning it a name. /// This method is intended to be the last call in a method-chaining setup, /// and the name is used for debugging, identification, and logging purposes. /// </summary> /// <param name="name">The name to assign to the CompoundTask.</param> /// <returns>The current CompoundTask instance (for method chaining).</returns> public CompoundTask Build(string name) { Name = name; return this; } }