Пример #1
0
 public void AddPreconditions(WorldGoal preconditions, bool returnPreconditions = true)
 {
     foreach (var stateful in preconditions.Keys)
     {
         if (!ContainsKey(stateful))
         {
             Add(stateful, new Goal());
         }
         foreach (var goalString in preconditions[stateful].Keys)
         {
             if (this[stateful].ContainsKey(goalString))
             {
                 this[stateful][goalString] = preconditions[stateful][goalString].Refine(this[stateful][goalString]);
             }
             else
             {
                 this[stateful].Add(goalString, preconditions[stateful][goalString]);
             }
         }
     }
     if (returnPreconditions)
     {
         preconditions.ReturnSelf();
     }
 }
Пример #2
0
 public void Init(Node parent, float runningCost, WorldGoal goal, GoapAction action, IStateful target)
 {
     this.parent      = parent;
     this.runningCost = runningCost;
     this.goal        = goal;
     this.action.Init(target, action);
 }
        /// <summary>
        /// A* forward search for a plan that satisfies the given goal.
        /// </summary>
        /// <returns>Returns null if a plan could not be found, or a list of the
        /// actions that must be performed, in order.</returns>
        public static Queue <ITransition> Plan(
            GoapAgent agent,
            WorldGoal goal)
        {
            var worldState = WorldState.Borrow();

            worldState[agent] = agent.GetState();
            var regressiveSearchGoal = RegressiveSearchWorldGoal.Borrow(goal);

            DebugUtils.Assert(worldState[agent].ContainsKey("x") &&
                              worldState[agent].ContainsKey("y") &&
                              worldState[agent].ContainsKey("z"),
                              "Agent's state must contain his position as 'x' and 'y' keys");

            var path = AStarSearch.Search(agent, regressiveSearchGoal, worldState, true);

            worldState.ReturnSelf();

            GoapAction.WithContext.ReportLeaks();
            State.ReportLeaks();
            WorldState.ReportLeaks();
            WorldGoal.ReportLeaks();
            RegressiveSearchWorldGoal.ReportLeaks();
            WorldEffects.ReportLeaks();

            return(path);
        }
 public WorldGoal(WorldGoal other) : base()
 {
     foreach (KeyValuePair <IStateful, Goal> kvp in other)
     {
         Goal goalCopy = new Goal(kvp.Value);                  // For deep copy
         this.Add(kvp.Key, goalCopy);
     }
 }
Пример #5
0
        /// <summary>
        /// Returns a WorldGoal that contains all the preconditions that the target
        /// of the action must satisfy.
        /// </summary>
        public virtual WorldGoal GetDependentPreconditions(IStateful agent, IStateful target)
        {
            var worldPreconditions = WorldGoal.Borrow();

            if (targetPreconditions.Count > 0)
            {
                worldPreconditions[target] = targetPreconditions;
            }
            return(worldPreconditions);
        }
Пример #6
0
        /// <summary>
        /// Returns a WorldGoal that contains all the preconditions that the agent
        /// must satisfy.
        /// </summary>
        public virtual WorldGoal GetIndependentPreconditions(IStateful agent)
        {
            var worldPreconditions = WorldGoal.Borrow();

            if (preconditions.Count > 0)
            {
                worldPreconditions[agent] = preconditions;
            }
            return(worldPreconditions);
        }
Пример #7
0
        public static RegressiveSearchWorldGoal Borrow(WorldGoal parent)
        {
            var obj = Borrow();

            foreach (var item in parent)
            {
                obj[item.Key] = item.Value;
            }
            return(obj);
        }
Пример #8
0
 public float CalculateHeuristicCost(WorldGoal goal, bool useCachedValue = true)
 {
     if (useCachedValue && cachedHeuristicCost >= 0f)
     {
         return(cachedHeuristicCost);
     }
     cachedHeuristicCost = 0f;
     // TODO: Calculate heuristic for A*.
     return(cachedHeuristicCost);
 }
Пример #9
0
        public static string PrettyPrint(WorldGoal state)
        {
            var s = new StringBuilder();

            foreach (var kvp in state)
            {
                var target = kvp.Key as Component;
                s.Append(target.name).Append(": ").Append(PrettyPrint(kvp.Value)).Append('\n');
            }
            return(s.ToString());
        }
Пример #10
0
 /// <summary>
 /// Check that all items in 'test' are in 'state'. If just one does not
 /// match or is not there then this returns false.
 /// </summary>
 public static bool DoConditionsApplyToWorld(WorldGoal test, WorldState state)
 {
     foreach (var targetGoal in test)
     {
         if (!state.ContainsKey(targetGoal.Key))
         {
             state [targetGoal.Key] = targetGoal.Key.GetState();
         }
         var targetState = state [targetGoal.Key];
         if (!DoConditionsApply(targetGoal.Value, targetState))
         {
             return(false);
         }
     }
     return(true);
 }
Пример #11
0
        // Create possible previous goal (before this actionwas made)
        public WorldGoal reverseApplyToWorldGoal(WorldGoal goal)
        {
            WorldGoal newGoal = new WorldGoal(goal);              //this is deep copied, see c'tor

            foreach (KeyValuePair <IStateful, Goal> agentGoal in goal)
            {
                GoapAgent     currAgent   = (GoapAgent)agentGoal.Key;
                Goal          currGoal    = agentGoal.Value;
                Goal          updatedGoal = this.effects.reverseApplyEffectsToGoal(currGoal);
                List <string> keys        = new List <string> (updatedGoal.Keys);
                foreach (string k in keys)
                {
                    if (updatedGoal [k] == null)
                    {
                        updatedGoal.Remove(k);
                    }
                }

                if (newGoal.ContainsKey(currAgent))
                {
                    newGoal [currAgent] = updatedGoal;
                }
                else
                {
                    newGoal.Add(currAgent, updatedGoal);
                }

                // Add target preconditions to new goal
                foreach (KeyValuePair <string, Condition> kvp in this.preconditions)
                {
                    if (!newGoal [currAgent].ContainsKey(kvp.Key))
                    {
                        newGoal [currAgent].Add(kvp.Key, new Condition(kvp.Value.comparison, kvp.Value.value));
                    }
                }
            }

            return(newGoal);
        }
Пример #12
0
 /// <summary>
 /// A plan was found for the given goal.
 /// The plan is a queue of actions that should be performed in order to
 /// fulfill the goal.
 /// </summary>
 public abstract void PlanFound(WorldGoal goal, Queue <ITransition> actions);
Пример #13
0
 /// <summary>
 /// No sequence of actions could be found for the supplied goal.
 /// Can be used to select another goal for next time.
 /// </summary>
 public abstract void PlanFailed(WorldGoal failedGoal);
        public bool isGoalCloser(WorldGoal currentGoal, WorldGoal possibleGoal)
        {
            bool res = false;

            foreach (KeyValuePair <IStateful, Goal> agentGoal in possibleGoal)
            {
                Goal possible = agentGoal.Value;
                // TODO: what if possible goal doesnt contain this person
                if (!currentGoal.ContainsKey(agentGoal.Key))
                {
                    continue;
                }
                else
                {
                    Goal current = currentGoal [agentGoal.Key];

                    //go through parent node's conditions
                    foreach (KeyValuePair <string, Condition> kvp in current)
                    {
                        // If initial state without this parameter, irrelevant and continue
                        if (this.ContainsKey(kvp.Key))
                        {
                            // If child node doesnt contain this goal, it is satisfied!
                            if (!possible.ContainsKey(kvp.Key))
                            {
                                res = true;
                            }

                            // Else - check if child goal is closer to inital state
                            else
                            {
                                StateValue sv       = this [kvp.Key];
                                Condition  currCond = kvp.Value;
                                Condition  possCond = possible [kvp.Key];
                                //if int check if new closer to wanted
                                if (sv.value.GetType() == typeof(int))
                                {
                                    if (sv.CheckCondition(currCond) && sv.CheckCondition(possCond))
                                    {
                                        continue;
                                    }
                                    if (sv.CheckCondition(currCond) && !sv.CheckCondition(possCond))
                                    {
                                        return(false);
                                    }
                                    if (!sv.CheckCondition(currCond) && sv.CheckCondition(possCond))
                                    {
                                        res = true;
                                        continue;
                                    }

                                    //now both conditions dont hold, check if possCond improves
                                    //assume both goals have same compare type
                                    switch (currCond.comparison)
                                    {
                                    case CompareType.Equal:
                                        res = (Mathf.Abs((int)sv.value - (int)currCond.value)) < (Mathf.Abs((int)sv.value - (int)possCond.value));
                                        break;

                                    case CompareType.LessThan:
                                        res = ((int)possCond.value - (int)sv.value) > ((int)currCond.value - (int)sv.value);
                                        break;

                                    case CompareType.LessThanOrEqual:
                                        res = ((int)possCond.value - (int)sv.value) > ((int)currCond.value - (int)sv.value);
                                        break;

                                    case CompareType.MoreThan:
                                        res = ((int)possCond.value - (int)sv.value) < ((int)currCond.value - (int)sv.value);
                                        break;

                                    case CompareType.MoreThanOrEqual:
                                        res = ((int)possCond.value - (int)sv.value) < ((int)currCond.value - (int)sv.value);
                                        break;

                                    case CompareType.NotEqual:
                                        res = (Mathf.Abs((int)sv.value - (int)currCond.value)) > (Mathf.Abs((int)sv.value - (int)possCond.value));
                                        break;
                                    }

                                    //if bool check if new matches while old doesnt
                                }
                                else if (sv.value.GetType() == typeof(bool))
                                {
                                    //assuming booleans will only get ModificationType.Set
                                    res = (sv.value != currCond.value && sv.value == possCond.value);
                                }

                                //if new cond worse - return false
                                if (res == false)
                                {
                                    //Debug.Log ("this Goal isnt any better! abort!");
                                    return(false);
                                }
                            }
                        }
                    }
                }
            }
            if (res == false)
            {
                //Debug.Log ("this Goal isnt any better! abort!");
            }
            else
            {
                //Debug.Log ("this Goal is better!");
            }
            return(res);
        }
Пример #15
0
 /// <summary>
 /// A plan was found for the given goal.
 /// The plan is a queue of actions that should be performed in order to
 /// fulfill the goal.
 /// </summary>
 public abstract void PlanFound(WorldGoal goal, Queue <GoapAction.WithContext> actions);
Пример #16
0
        /// <summary>
        /// A* forward search for a plan that satisfies the given goal.
        /// </summary>
        /// <returns>Returns null if a plan could not be found, or a list of the
        /// actions that must be performed, in order.</returns>
        public static Queue <GoapAction.WithContext> Plan(
            GoapAgent agent,
            List <GoapAction> availableActions,
            WorldGoal goal)
        {
            var exploredNodes = new Dictionary <WorldState, Node> (WorldStateComparer.instance);
            var closedSet     = new HashSet <WorldState> (WorldStateComparer.instance);
            var openSet       = new FastPriorityQueue <Node> (MAX_FRINGE_NODES);

            var currentNode = Node.pool.Borrow();

            currentNode.Init(null, 0f, goal, null, null);
//			currentNode.position = Vector2.zero;
            currentNode.position = (agent as Component).transform.position;

            openSet.Enqueue(currentNode, 0f);
            int iterations = 0;

            while (openSet.Count > 0 && iterations < MAX_FRINGE_NODES - 10)
            {
                iterations++;

                currentNode = openSet.Dequeue();

                //TODO: delete print
                //Debug.Log ("current world goal: " + GoapAgent.PrettyPrint(currentNode.goal));

                if (DoConditionsApply(currentNode.goal[agent], agent.GetState()))
                {
                    DebugUtils.Log("Selected plan with cost: " + currentNode.Score);
                    var plan = UnwrapPlan(currentNode);
                    //DebugUtils.Log("the plan: " + GoapAgent.PrettyPrint(plan));

                    // Return all nodes.
                    Node.pool.ReturnAll();

                    // Check for leaks in the pools:
                    //DebugUtils.LogError("Nodes: " + Node.pool.Count);
                    //DebugUtils.LogError("WithContext: " + GoapAction.WithContext.pool.Count);
                    //DebugUtils.LogError("WorldState: " + WorldState.pool.Count);

                    return(plan);
                }

                foreach (GoapAction action in availableActions)
                {
                    //TODO: delete print
                    //Debug.Log("considering " + action.name);

                    WorldGoal possibleChildGoal = action.reverseApplyToWorldGoal(currentNode.goal);

                    //Debug.Log ("new goal will be: " + GoapAgent.PrettyPrint(possibleChildGoal));

                    if (agent.GetState().isGoalCloser(currentNode.goal, possibleChildGoal))
                    {
                        List <IStateful> targets = action.GetAllTargets(agent);

                        // No targets, move to next action
                        if (targets.Count == 0)
                        {
                            continue;
                        }

                        float     minCost       = 99999f;
                        float     tempCost      = 0f;
                        IStateful closestTarget = null;
                        Vector2   newPosition   = currentNode.position;
                        foreach (var target in targets)
                        {
                            //DebugUtils.Log ("targets...");
                            //TODO: check target preconds, make sure this works
                            if (goal.ContainsKey(target))
                            {
                                if (!DoConditionsApply(goal [target], target.GetPerceivedState()))
                                {
                                    continue;
                                }
                            }

                            if (action.RequiresInRange())
                            {
                                tempCost = action.CalculateCost(currentNode.position, target);
                                if (tempCost < minCost)
                                {
                                    minCost       = tempCost;
                                    closestTarget = target;
                                    newPosition   = (target as Component).transform.position;
                                    DebugUtils.Log("minCost: " + minCost);
                                    DebugUtils.Log("closestTarget: " + closestTarget);
                                }
                                //DebugUtils.Log ("calculating tempCost");
                            }
                            else
                            {
                                closestTarget = target;
                                tempCost      = 9999;
                                DebugUtils.Log("+++ closestTarget: " + closestTarget);
                                break;
                            }
                        }

                        float cost = currentNode.runningCost + action.workDuration + tempCost;

                        Node newChiledNode = Node.pool.Borrow();
                        DebugUtils.Log("*** closestTarget: " + closestTarget);
                        newChiledNode.Init(currentNode, cost, possibleChildGoal, action, closestTarget);
                        newChiledNode.position = newPosition;
                        openSet.Enqueue(newChiledNode, newChiledNode.runningCost);
                    }

                    //TODO: delete 'else' scope
                    else
                    {
                        //DebugUtils.Log (action.name + " doesnt improve goal");
                    }
                }
            }
            //TODO: return plan failed #yoel
            return(null);
        }