// --------------------------

    // Start is called before the first frame update
    void Start()
    {
        navMeshAgent             = this.gameObject.GetComponent <NavMeshAgent>();
        navMeshAgent.autoBraking = false;                    // disable auto braking for continuous movement

        this.monsterYellingText.gameObject.SetActive(false); // disable UI yelling text

        // generate an HTN tree for this monster
        rootNode = generateHTNtree();

        // generate a World State
        HTN_WorldState ws = new HTN_WorldState(false, false, false, false, false);  // set all false initially, let the update function to update WorldState

        this.worldState = ws;

        // create a HTN planner
        planner = new HTN_Planner(this, worldState);
    }
Beispiel #2
0
    /// <summary>
    /// Function to generate a plan for a given root node of HTN tree
    /// </summary>
    /// <param name="rootNode"></param>
    public void planning(HTN_node rootNode)
    {
        HTN_WorldState   state         = this.currentWorldState.clone(); // make a copy of the current state
        ArrayList        finalPlanList = new ArrayList();
        Stack <HTN_node> tasksNodes    = new Stack <HTN_node>();

        // stack for store Method node for backtracking
        Stack <ArrayList> backTrackingMethods = new Stack <ArrayList>();  // each list in this stack is a list of methods
        // stack for store planList for backtracking
        Stack <ArrayList>      backTrackingPlan = new Stack <ArrayList>();
        Stack <HTN_WorldState> states           = new Stack <HTN_WorldState>(); // store the copy of states for backtracking


        tasksNodes.Push(rootNode);  // put the root node into the task stack

        // while the stack is not empty
        while (!(tasksNodes.Count == 0))
        {
            HTN_node taskNode = tasksNodes.Pop();

            // if the node is a compound node
            if (taskNode is HTN_CompoundNode)
            {
                ArrayList methods = ((HTN_CompoundNode)taskNode).findSatisfiedMethods(this.currentWorldState);
                //HTN_MethodNode method = ((HTN_CompoundNode)taskNode).findSatisfiedMethod(this.currentWorldState);
                HTN_MethodNode method = (HTN_MethodNode)methods[0];
                methods.RemoveAt(0);

                if (method != null)
                {
                    // store the plan and the next method node for backtracking when needed
                    backTrackingPlan.Push(new ArrayList(finalPlanList));  // clone the current plan list
                    backTrackingMethods.Push(methods);
                    states.Push(state.clone());

                    // push the subtasks of this method into the list (push backward since we want the first subtask to be pop next)
                    for (int i = method.getChildren().Count - 1; i >= 0; i--)
                    {
                        tasksNodes.Push((HTN_node)method.getChildren()[i]);
                    }
                }
                else
                {
                    // restore to the saved backtracking state
                    state         = states.Pop();
                    finalPlanList = backTrackingPlan.Pop();
                    tasksNodes.Clear();  // empty the tasksNode stack

                    // pop a methods list
                    ArrayList btMethods = backTrackingMethods.Pop();
                    while (btMethods.Count == 0)
                    {
                        btMethods = backTrackingMethods.Pop();
                    }

                    // get the first method in that list
                    HTN_MethodNode btMethodNode = (HTN_MethodNode)btMethods[0];
                    btMethods.RemoveAt(0);  // delete that method from the list
                    if (btMethods.Count > 0)
                    {
                        backTrackingMethods.Push(btMethods);  // put the method list back
                    }
                    // push the subtasks of this method into the list (push backward since we want the first subtask to be pop next)
                    for (int i = btMethodNode.getChildren().Count - 1; i >= 0; i--)
                    {
                        tasksNodes.Push((HTN_node)btMethodNode.getChildren()[i]);
                    }
                }
            }
            else  // primative node
            {
                // if the precondition is met
                if (((HTN_PrimitiveNode)taskNode).verifyPrecondition(state))
                {
                    // apply the effect of this task on the world state
                    ((HTN_PrimitiveNode)taskNode).applyTask(state);
                    finalPlanList.Add(taskNode);  // add this taskNode to the plan list

                    // if this primitive task is the last in the stack, our planning is finish
                    if (tasksNodes.Count == 0)
                    {
                        break;
                    }
                }
                else
                {
                    // restore to the saved backtracking state
                    state         = states.Pop();
                    finalPlanList = backTrackingPlan.Pop();
                    tasksNodes.Clear();  // empty the tasksNode stack

                    // pop a methods list
                    ArrayList btMethods = backTrackingMethods.Pop();
                    while (btMethods.Count == 0)
                    {
                        btMethods = backTrackingMethods.Pop();
                    }

                    // get the first method in that list
                    HTN_MethodNode btMethodNode = (HTN_MethodNode)btMethods[0];
                    btMethods.RemoveAt(0);  // delete that method from the list
                    if (btMethods.Count > 0)
                    {
                        backTrackingMethods.Push(btMethods);  // put the method list back
                    }
                    // push the subtasks of this method into the list (push backward since we want the first subtask to be pop next)
                    for (int i = btMethodNode.getChildren().Count - 1; i >= 0; i--)
                    {
                        tasksNodes.Push((HTN_node)btMethodNode.getChildren()[i]);
                    }
                }
            }
        }

        this.plan = finalPlanList;  // set the current plan to the final plan list
    }
 /// <summary>
 /// Function to add child node to this node
 /// </summary>
 /// <param name="childNode"></param>
 public void addChild(HTN_node childNode)
 {
     this.children.Add(childNode);
 }