//HTN forward plan builder private void BuildPlan() { node cur; tasks = new Queue <node>(); plan = new Queue <string>(); tasks.Enqueue(htn_tree.rootNode); while (tasks.Count > 0) { bool preConditionsMet = false; cur = tasks.Dequeue(); //rootnode is a compound task we need to evaluate regardless of wolrd state if (cur.t == node.type.Root) { compound_task c_cur = (compound_task)cur; LoadChildren(c_cur.children); } //normal compound nodes extraction and evaluation else if (cur.t == node.type.Compound) { compound_task c_cur = (compound_task)cur; preConditionsMet = EvalCompoundPreConditions(c_cur.behaviorName); if (preConditionsMet == true) { //in a sequence all tasks are evaluated if (c_cur.st == compound_task.subType.Sequence) { LoadChildren(c_cur.children); } //in the selector 1 random task is evaluated else if (c_cur.st == compound_task.subType.Selector) { int index = Random.Range(0, c_cur.children.Count); List <node> l = new List <node>(); l.Add(c_cur.children[index]); LoadChildren(l); } } } //primitive tasks preconditions are evaluated one last time before being added to the execution plan. A failure triggers a replan. else if (cur.t == node.type.Primitive) { primitive_task p_cur = (primitive_task)cur; preConditionsMet = EvalPrimitivePreConditions(p_cur.taskName); if (preConditionsMet == true) { plan.Enqueue(p_cur.taskName); } else { planIsValid = false; break; } } } }
//default constructor builds the htn tree model in the implementation doc public monster_htn() { monster = GameObject.Find("Monster"); m = monster.GetComponent <monster_controller>(); //define rootNode node rootNode = new compound_task(node.type.Root, "beAMonster"); rootNode.children = new List <node>(); rootNode.children.Add(new compound_task(rootNode, node.type.Compound, compound_task.subType.Sequence, "wander")); rootNode.children.Add(new compound_task(rootNode, node.type.Compound, compound_task.subType.Sequence, "attack")); //build left handside of the htn: wandering behavior compound_task wanderNode = (compound_task)rootNode.children[0]; wanderNode.children = new List <node> { new compound_task(wanderNode, node.type.Compound, compound_task.subType.Selector, "navSpeed"), //movement type new primitive_task(wanderNode, node.type.Primitive, "setNavDest"), //choose dest new primitive_task(wanderNode, node.type.Primitive, "idle") //rest }; compound_task navSpeedNode = (compound_task)wanderNode.children[0]; navSpeedNode.children = new List <node> { new primitive_task(navSpeedNode, node.type.Primitive, "walk"), new primitive_task(navSpeedNode, node.type.Primitive, "run") }; //build the right handside of the tree: attack behavior compound_task attackNode = (compound_task)rootNode.children[1]; attackNode.children = new List <node> { new primitive_task(attackNode, node.type.Primitive, "getAngry"), //change skin color new compound_task(attackNode, node.type.Compound, compound_task.subType.Sequence, "findObjectToThrow"), //pick up object new compound_task(attackNode, node.type.Compound, compound_task.subType.Selector, "throw"), //throw new primitive_task(wanderNode, node.type.Primitive, "recover") //rest }; compound_task findObjNode = (compound_task)attackNode.children[1]; findObjNode.children = new List <node> { new primitive_task(findObjNode, node.type.Primitive, "findObj"), //find closest obj new primitive_task(findObjNode, node.type.Primitive, "navToObj"), //navigate to it new primitive_task(findObjNode, node.type.Primitive, "pickUp") //pick it up }; compound_task throwNode = (compound_task)attackNode.children[2]; throwNode.children = new List <node> { new compound_task(throwNode, node.type.Compound, compound_task.subType.Sequence, "superThrow"), //throw rock new primitive_task(throwNode, node.type.Primitive, "objectThrow") //throw object }; compound_task superThrowNode = (compound_task)throwNode.children[0]; superThrowNode.children = new List <node> { new primitive_task(superThrowNode, node.type.Primitive, "growl"), //growl new primitive_task(superThrowNode, node.type.Primitive, "objectThrow") //throw object }; }