Beispiel #1
0
 public GOAPNode(GOAPNode _parent, float _runningCost, Dictionary <string, bool> _state, GOAPAction _action)
 {
     parent      = _parent;
     runningCost = _runningCost;
     state       = _state;
     action      = _action;
 }
Beispiel #2
0
 public GOAPNode(GOAPNode p, GOAPAction a, Dictionary <Condition, object> s, float c)
 {
     parent    = p;
     action    = a;
     state     = s;
     costSoFar = c;
 }
Beispiel #3
0
    //Currently using DFS, goal to switch to A*
    private void BuildGraph(GOAPNode root, HashSet <GOAPAction> usableActions, Dictionary <Condition, object> goal, int searchDepth, List <GOAPNode> solutionNodes)
    {
        if (searchDepth > MAX_DEPTH)
        {
            return;
        }
        //O(N^2)
        foreach (GOAPAction action in usableActions)
        {
            if (usedActions.Contains(action))
            {
                continue;
            }

            if (action.CheckPreConditions(root.state))
            {
                Dictionary <Condition, object> newState = action.ApplyPostConditionsToState(root.state);
                GOAPNode node = new GOAPNode(root, action, newState, root.costSoFar + action.cost);

                if (GoalFromState(goal, newState))
                {
                    solutionNodes.Add(node);
                }
                else
                {
                    usedActions.Add(action);
                    BuildGraph(node, usableActions, goal, searchDepth + 1, solutionNodes);
                    usedActions.Remove(action);
                }
            }
        }
    }
Beispiel #4
0
        public void ShouldBeIndependentOfClone()
        {
            GOAPNode original = new GOAPNode(new WorldState(ws), null);
            GOAPNode clone    = (GOAPNode)original.Clone();

            clone.WorldState.SetToken("a", !(bool)original.WorldState.GetValue("a"));
            Assert.AreNotEqual(clone.WorldState.GetValue("a"), original.WorldState.GetValue("a"));
        }
Beispiel #5
0
    public Queue <GOAPAction> CreatePlan(NPC agent, Dictionary <Condition, object> goal)
    {
        Dictionary <Condition, object> currentNPCState = agent.GetNPCState();

        //Check to see if goal is already fulfilled
        if (GoalFromState(goal, currentNPCState))
        {
            return(null);
        }

        HashSet <GOAPAction> usableActions = GetUsableActions(agent.AllActions, currentNPCState);
        List <GOAPNode>      solutionNodes = new List <GOAPNode>();

        GOAPNode        root  = new GOAPNode(null, null, currentNPCState, 0);
        List <GOAPNode> nodes = new List <GOAPNode>();

        BuildGraph(root, agent.AllActions, goal, 0, solutionNodes);

        if (solutionNodes.Count == 0)
        {
            return(null);
        }

        //Found at least one solution
        float    minCost      = solutionNodes[0].costSoFar;
        GOAPNode cheapestNode = solutionNodes[0];

        //Find the cheapest(best) solution
        for (int i = 1; i < solutionNodes.Count; i++)
        {
            cheapestNode = solutionNodes[i].costSoFar < minCost ? solutionNodes[i] : cheapestNode;
            minCost      = Mathf.Min(minCost, solutionNodes[i].costSoFar);
        }

        GOAPNode          curNode = cheapestNode;
        List <GOAPAction> path    = new List <GOAPAction>();

        while (curNode != null)
        {
            if (curNode.action != null)
            {
                path.Insert(0, curNode.action);
            }

            curNode = curNode.parent;
        }

        Queue <GOAPAction> plan = new Queue <GOAPAction>();

        foreach (GOAPAction a in path)
        {
            plan.Enqueue(a);
        }

        return(plan);
    }
Beispiel #6
0
        public void ShouldHaveSameTokensAsClone()
        {
            foreach (WorldStateToken token in tokens)
            {
                ws.SetToken(token);
            }
            generic_astar.Action action = new generic_astar.Action("test_action", new List <WorldStateToken>()
            {
            }, new List <WorldStateToken>()
            {
            }, 10);
            GOAPNode node  = new GOAPNode(ws, action);
            GOAPNode clone = (GOAPNode)node.Clone();

            foreach (WorldStateToken token in tokens)
            {
                Assert.AreEqual(token.Value, clone.WorldState.GetValue(token.Name));
            }
        }
Beispiel #7
0
        /// <summary> 构建树并返回所有计划 </summary>
        /// <param name="_parent">父节点,不可为空</param>
        /// <param name="_usableActions">所有可行行为</param>
        /// <param name="_goal">目标计划</param>
        /// <param name="_leaves">已找到的所有计划</param>
        /// <returns>是否找到计划</returns>
        private bool BuildGraph(GOAPNode _parent, List <GOAPAction> _usableActions, GOAPGoal _goal, int _depth, int _maxDepth, List <GOAPNode> _leaves)
        {
            if (_maxDepth >= 1 && _depth >= _maxDepth)
            {
                return(false);
            }

            foreach (GOAPAction action in _usableActions)
            {
                // 不允许出现两个连续的相同行为
                if (_parent == null || action == _parent.action || !action.IsProceduralPrecondition(_parent.state))
                {
                    continue;
                }

                if (InState(_parent.state, action.Preconditions))
                {
                    // 造成效果影响当前状态
                    Dictionary <string, bool> currentState = PopulateState(_parent.state, action.Effects);

                    // 生成动作完成的节点链,成本累加
                    GOAPNode node = NodePool.Spawn(_parent, _parent.runningCost + action.Cost, currentState, action);

                    // 如果当前状态能够达成目标
                    if (currentState.TryGetValue(_goal.Key, out bool value) && value.Equals(_goal.Value))
                    {
                        _leaves.Add(node);
                    }
                    else
                    {
                        BuildGraph(node, _usableActions, _goal, ++_depth, _maxDepth, _leaves);
                    }
                }
            }

            return(_leaves.Count > 0);
        }
Beispiel #8
0
        /// <summary> 定制最优计划 </summary>
        /// <param name="_agent">代理</param>
        /// <param name="_availableActions">所有可用行为</param>
        /// <param name="_currentStates">当前状态</param>
        /// <param name="_goal">目标状态,想要达到的状态</param>
        public void Plan(GOAPAction[] _availableActions,
                         Dictionary <string, bool> _currentStates, GOAPGoal _goal, int _maxDepth, ref Queue <GOAPAction> _plan)
        {
            if (_currentStates.TryGetValue(_goal.Key, out bool value) && value.Equals(_goal.Value))
            {
                return;
            }

            NodePool.RecycleAll();

            // 所有可用的行为
            usableActions.Clear();
            foreach (var action in _availableActions)
            {
                if (action.IsUsable())
                {
                    action.DynamicallyEvaluateCost();
                    usableActions.Add(action);
                }
            }

            // 根节点
            root = NodePool.Spawn(null, 0, _currentStates, null);
            // 所有能达到目标的节点
            leaves.Clear();
            // 成本最低的计划节点
            cheapestNode = null;
            // 成本最低计划
            _plan.Clear();

            // 如果通过构建节点树找到了能够达成目标的计划
            if (BuildGraph(root, usableActions, _goal, 0, _maxDepth, leaves))
            {
                Stack <GOAPAction> goapActionStack = Stack_Pool.Spawn();

                foreach (GOAPNode leaf in leaves)
                {
                    if (cheapestNode == null)
                    {
                        cheapestNode = leaf;
                    }
                    else if (cheapestNode.runningCost > leaf.runningCost)
                    {
                        cheapestNode = leaf;
                    }
                }

                // 向上遍历并添加行为到栈中,直至根节点,因为从后向前遍历
                while (cheapestNode != null)
                {
                    goapActionStack.Push(cheapestNode.action);

                    if (cheapestNode.parent.action != null)
                    {
                        cheapestNode = cheapestNode.parent;
                    }
                    else
                    {
                        break;
                    }
                }

                //goapActions = new Queue<Action>();
                // 再将栈压入到队列中
                while (goapActionStack.Count > 0)
                {
                    _plan.Enqueue(goapActionStack.Pop());
                }
                Stack_Pool.Recycle(goapActionStack);
            }

            // 用完回收所有对象
            DictionaryObjPool.RecycleAll();
        }
Beispiel #9
0
 public void TestGOAPConstructor()
 {
     GOAPNode state =
 }