public string PathToString() { var node = this; var s = string.Empty; while (node.parent != null) { s = GoapAgent.PrettyPrint(node.action) + ">" + s; node = node.parent; } return(s); }
public static WithContext Borrow(GoapAction action, GoapAgent agent, IStateful target) { var actionWithContext = pool.Borrow(); actionWithContext.actionData = action; actionWithContext.agent = agent; actionWithContext.target = target; actionWithContext.startTime = 0; actionWithContext.isInRange = false; actionWithContext.isDone = false; return(actionWithContext); }
protected virtual bool CanDoNow(GoapAgent agent, IStateful target) { var worldState = WorldState.pool.Borrow(); worldState.Clear(); worldState[agent] = agent.GetState(); worldState[target] = target.GetState(); var conditions = GetDependentPreconditions(agent, target); bool result = GoapPlanner.DoConditionsApplyToWorld(conditions, worldState); WorldState.pool.Return(worldState); return(result); }
protected virtual bool CanDoNow(GoapAgent agent, IStateful target) { var worldState = WorldState.Borrow(); worldState[agent] = agent.GetState(); worldState[target] = target.GetState(); // Since the action is a part of the plan, its preconditions on the agent // should apply. var doesApply = worldState.IsGoalState(GetIndependentPreconditions(agent)); // NOTE: If the agent's state is volatile and can change outside of the // agent's plan, comment out this assertion. DebugUtils.AssertWarning( doesApply, "WARNING: Possible bug in definition of " + name + ". The agent " + agent.name + " planned to do it but now its state does not allow it"); // Need to check that the target's state still apply to the preconditions // defined by the action. doesApply = doesApply && worldState.IsGoalState(GetDependentPreconditions(agent, target)); worldState.ReturnSelf(); return(doesApply); }
/// <summary> /// Run the action. /// Returns True if the action performed successfully or false if /// something happened and it can no longer perform. In this case the /// action queue should clear out and the goal cannot be reached. /// </summary> public bool Perform(GoapAgent agent) { if (Mathf.Approximately(startTime, 0f)) { if (!actionData.CanDoNow(agent, target)) { return(false); } startTime = Time.time; } if (Time.time - startTime > actionData.workDuration) { if (!actionData.CanDoNow(agent, target)) { return(false); } DebugUtils.Log(GetType().Name + " Time is up - am I done?"); return(actionData.OnDone(agent, this)); } return(true); }
// 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); }
/// <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(); DebugUtils.Assert(worldState[agent].ContainsKey("x") && worldState[agent].ContainsKey("x"), "Agent's state must contain his position as 'x' and 'y' keys"); var path = AStarSearch.Search(agent, worldState, goal); GoapAction.WithContext.ReportLeaks(); State.ReportLeaks(); WorldState.ReportLeaks(); WorldGoal.ReportLeaks(); WorldEffects.ReportLeaks(); return(path); }
/// <summary> /// Returns false if the action can not be performed. /// Override this to implement the affect of completing the action. /// </summary> protected virtual bool OnDone(GoapAgent agent, WithContext context) { context.isDone = true; DebugUtils.Log(GetType().Name + " DONE!"); return(true); }
public int GetHashCode(WorldState obj) { return(GoapAgent.PrettyPrint(obj).GetHashCode()); }
/// <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); }