Newer
Older
Hierarchical-Task-Network-Unity-3D / Assets / Scripts / HTN / HTNPlanner.cs
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Agent))]
public class HTNPlanner : MonoBehaviour
{
    // ================== VARIABLES ==================
    private Plan plan;
    private Worldstate state;
    private Agent agent;
    private Customer customer;
    [SerializeField] private bool pause = false;
    [SerializeField] private Queue<CompoundTask> taskQueue = new();

    // ================== PROPERTIES ==================
    public Worldstate WorldState => state;

    public Agent Agent => agent;
    public Customer Customer => customer;
    public bool IsBusy => plan != null;

    // ================== BUILT-IN METHODS ==================
    private void Awake()
    {
        agent = GetComponent<Agent>();
        customer = GetComponent<Customer>();
    }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        //Get world State instance
        state = Worldstate.Instance;

    }

    // Update is called once per frame
    void Update()
    {
        if (plan == null)
        {
            CreateAPlan();
        }

        if (plan != null && plan.Status == Plan.PlanStatus.Running) {
            Debug.Log("Current Task: " + plan.CurrentTask);

            if (plan.CurrentTask is PrimitiveTask)
            {
                PrimitiveTask primitiveTask = (PrimitiveTask)plan.CurrentTask;

                foreach (Condition condition in primitiveTask.Postconditions)
                {
                    Debug.Log($"Current PostCondition: {condition.Name} is {condition.IsConditionMet(this)}");
                }
            }
            plan.ExecutePlan(this);
        }

        else if(taskQueue.Count > 0 && plan != null && plan.Status == Plan.PlanStatus.Completed)
        {
            plan = new Plan(taskQueue.Dequeue(), this);
        }

        else
        {
            //Debug.LogWarning("There are no more plans to Execute");
        }
    }

    private void CreateAPlan()
    {
        //Customer Casting
        Customer customer = Agent as Customer;

        //Adds Compound Tasks to the Queue
        if (customer.wishList.Count > 0)
        {
            foreach (int productID in customer.wishList.Keys)
            {
                Debug.Log("Number of producs in the world state: " + state.Products.Count);
                Product product = state.Products.Find(p => p.ID == productID);

                if (product != null)
                {
                    taskQueue.Enqueue(new ShopProduct(this, product.ItemName));
                }

                else
                {
                    Debug.LogError("Product is NULL!");
                }
            }

            taskQueue.Enqueue(new Payment(this));
        }

        else
        {
            Debug.LogError("Wish List is Empty!");
        }

        //Create a plan
        plan = new Plan(taskQueue.Dequeue(), this);
    }
}