Example #1
0
        public List <PlannerNode <TKey, TValue> > GetNeighbours(PlannerNode <TKey, TValue> _baseNode)
        {
            m_NeighbourNodes.Clear();

            WorldStateModifier <TKey, TValue> basePreconditions    = _baseNode.Action?.GetPreconditions();
            WorldState <TKey, TValue>         worldStateAtBaseNode = _baseNode.GetWorldStateAtNode();
            Goal <TKey, TValue> goalWorldStateAtBaseNode           = _baseNode.GetGoalWorldStateAtNode();

            WorldState <TKey, TValue> remainingGoals = goalWorldStateAtBaseNode - worldStateAtBaseNode;

            // We implement regressive A* for GOAP by chaining action preconditions to action effects until all preconditions are fulfilled.
            // For this planner, neighbours are nodes that fulfil any of the remaining goals of the base node without conflicting with any of its preconditions.

            foreach (IAction <TKey, TValue> possibleAction in m_CurrentAgent.GetActionSet())
            {
                var effects = possibleAction.GetEffects();

                if (!effects.ContainsAny(remainingGoals))
                {
                    continue;
                }

                if (effects.ConflictsAny(basePreconditions))
                {
                    continue;
                }

                PlannerNode <TKey, TValue> plannerNode = GetAvailablePlannerNode();
                plannerNode.Init(possibleAction);

                plannerNode.CalculateWorldStateAtNode(worldStateAtBaseNode);
                plannerNode.CalculateGoalWorldStateAtNode(goalWorldStateAtBaseNode);

                bool foundInUsed = false;
                foreach (PlannerNode <TKey, TValue> usedNode in m_UsedNodes)
                {
                    if (usedNode.Equals(plannerNode))
                    {
                        plannerNode = usedNode;
                        foundInUsed = true;
                        break;
                    }
                }

                m_NeighbourNodes.Add(plannerNode);

                if (!foundInUsed)
                {
                    m_UsedNodes.Add(plannerNode);
                }
            }

            return(m_NeighbourNodes);
        }
Example #2
0
        public GoalPlanPair <TKey, TValue> GenerateGoalPlanPairForAgent(IAgent <TKey, TValue> _agent)
        {
            m_CurrentAgent = _agent;

            Stack <PlannerNode <TKey, TValue> > foundPath = null;
            bool newGoalBetterThanActiveGoal = false;

            m_GoalPlanPair.GoalInstance = null;
            m_GoalPlanPair.PlanInstance = null;

            for (var goalQueue = m_CurrentAgent.CalculateSortedGoals(); goalQueue.Count > 0;)
            {
                SortableGoal <TKey, TValue> goal = goalQueue.Dequeue();

                PlannerNode <TKey, TValue> agentNode = new PlannerNode <TKey, TValue>();
                agentNode.CalculateWorldStateAtNode(_agent.GetWorkingMemory());
                agentNode.CalculateGoalWorldStateAtNode(goal);

                foundPath = m_Pathfinder.FindPath(agentNode, null);
                if (foundPath != null && foundPath.Count > 0)
                {
                    newGoalBetterThanActiveGoal = _agent.IsGoalBetterThanActiveGoal(goal);
                    if (newGoalBetterThanActiveGoal)
                    {
                        m_GoalPlanPair.GoalInstance = goal;
#if UNITY_EDITOR
                        _agent.CreatePlanHierarchy(foundPath.Last(), m_Pathfinder.GetOpenNodes(), m_Pathfinder.GetClosedNodes());
#endif
                    }
                    break;
                }
            }

            m_GoalPlanPair.PlanInstance = new Plan <TKey, TValue>();
            if (newGoalBetterThanActiveGoal && foundPath != null)
            {
                foreach (PlannerNode <TKey, TValue> pathNode in foundPath)
                {
                    if (pathNode.Action != null)
                    {
                        m_GoalPlanPair.PlanInstance.Push(pathNode.Action);
                    }
                }
            }

            m_UsedNodes.Clear();
            RecycleUsedNodes();

            return(m_GoalPlanPair);
        }