/// <summary>
    /// Function to generate a HTN tree for this monster
    /// </summary>
    /// <returns></returns>
    HTN_node generateHTNtree()
    {
        // the image of this tree is shown in PDF file

        // root node
        HTN_CompoundNode root = new HTN_CompoundNode();

        // create children methods
        HTN_MethodNode method1 = new HTN_MethodNode(Task.DISTANCE_ATTACK);
        HTN_MethodNode method2 = new HTN_MethodNode(Task.IDLE);

        root.addChild(method1);
        root.addChild(method2);

        // create children tasks for method1
        //HTN_CompoundNode crate_attack = new HTN_CompoundNode();
        //HTN_CompoundNode rock_attack = new HTN_CompoundNode();
        HTN_CompoundNode distance_attack = new HTN_CompoundNode();

        HTN_MethodNode crate_attackM = new HTN_MethodNode(Task.CRATE_ATTACK);
        HTN_MethodNode rock_attackM  = new HTN_MethodNode(Task.ROCK_ATTACK);

        crate_attackM.addChild(new HTN_PrimitiveNode(Task.MOVE_TO_CRATE));
        crate_attackM.addChild(new HTN_PrimitiveNode(Task.THROW_CRATE));
        rock_attackM.addChild(new HTN_PrimitiveNode(Task.MOVE_TO_ROCK));
        rock_attackM.addChild(new HTN_PrimitiveNode(Task.THROW_ROCK));

        //method1.addChild(crate_attack);
        //method1.addChild(rock_attack);
        method1.addChild(distance_attack);


        //crate_attack.addChild(crate_attackM);
        //rock_attack.addChild(rock_attackM);
        distance_attack.addChild(crate_attackM);
        distance_attack.addChild(rock_attackM);


        // add child task for method2
        HTN_CompoundNode idle = new HTN_CompoundNode();

        HTN_MethodNode yelling_wanderM = new HTN_MethodNode(Task.YELLING_WANDER);
        HTN_MethodNode wanderM         = new HTN_MethodNode(Task.ONLY_WANDER);

        yelling_wanderM.addChild(new HTN_PrimitiveNode(Task.YELLING));
        yelling_wanderM.addChild(new HTN_PrimitiveNode(Task.WANDER));
        wanderM.addChild(new HTN_PrimitiveNode(Task.WANDER));

        method2.addChild(idle);
        idle.addChild(yelling_wanderM);
        idle.addChild(wanderM);


        //method2.addChild(new HTN_PrimitiveNode(Task.WANDER));



        return(root);
    }
예제 #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
    }