/// <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); }
private float RegressiveSearchCost(RegressiveSearchWorldGoal goal) { DebugUtils.Assert(goal != null, "CalculateCost used with something other than WorldState or RegressiveSearchWorldGoal"); // Calculate travel cost. var travelCost = 0f; if (actionData.RequiresInRange()) { if (goal.agentGoalPosition != null) { var goalPosition = (Vector3)goal.agentGoalPosition; var obj = target as Component; var travelVector = obj.transform.position - goalPosition; travelCost = travelVector.magnitude; //DebugUtils.Log(travelCost + " to " + obj.name); } } return(actionData.cost + travelCost); }
private RegressiveSearchWorldGoal ApplyInReverse(RegressiveSearchWorldGoal goal, bool inPlace = false) { var effects = actionData.GetDependentEffects(agent, target); goal = goal.RegressWorldGoal(effects, inPlace); effects.ReturnSelf(); goal.AddPreconditions(actionData.GetIndependentPreconditions(agent)); goal.AddPreconditions(actionData.GetDependentPreconditions(agent, target)); // Apply movement. if (actionData.RequiresInRange()) { // Don't add the position as a goal because we don't have a // just MoveAction to satisfy this goal. Instead, we calculate // this cost as part of the heuristic. var obj = target as Component; goal.agentGoalPosition = obj.transform.position; } return(goal); }
/// <summary> /// Regress worldGoal to before effects /// </summary> public RegressiveSearchWorldGoal RegressWorldGoal(WorldEffects worldEffects, bool inPlace = false) { var worldGoal = this; if (!inPlace) { worldGoal = RegressiveSearchWorldGoal.Borrow(); foreach (var goal in this) { worldGoal[goal.Key] = goal.Value; } } // Reverse change. foreach (var effects in worldEffects) { if (worldGoal.ContainsKey(effects.Key)) { worldGoal[effects.Key] = worldGoal[effects.Key].RegressGoal(effects.Value); } } return(worldGoal); }
private float RegressiveSearchCost(RegressiveSearchWorldGoal goal) { DebugUtils.Assert(goal != null, "CalculateCost used with something other than WorldState or RegressiveSearchWorldGoal"); // Calculate travel cost. var travelCost = 0f; if (actionData.RequiresInRange()) { if (goal.agentGoalPosition != null) { var goalPosition = (Vector2)goal.agentGoalPosition; var obj = target as Component; if (obj == null || obj.ToString() == "Null" || obj.ToString() == "null") { Debug.LogError("obj is NULL (RegressiveSearchCost)"); return(Mathf.Infinity); } var travelVector = (Vector2)obj.transform.position - goalPosition; travelCost = travelVector.magnitude; //DebugUtils.Log(travelCost + " to " + obj.name); } } return(actionData.cost + travelCost); }