Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed resolver traversing action with unresolvable condition #80

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Package/Runtime/CrashKonijn.Goap.Resolver/GraphResolverJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ public void Execute()
closedSet.TryAdd(currentNode.Index, currentNode);
openSet.Remove(currentNode.Index);

// If this node has a condition that is false and has no connections, it is unresolvable
if (this.HasUnresolvableCondition(currentNode.Index))
{
continue;
}

foreach (var conditionIndex in this.NodeConditions.GetValuesForKey(currentNode.Index))
{
if (runData.ConditionsMet[conditionIndex])
Expand All @@ -114,6 +120,7 @@ public void Execute()
var newG = currentNode.G + this.RunData.Costs[neighborIndex];
NodeData neighbor;

// Current neighbour is not in the open set
if (!openSet.TryGetValue(neighborIndex, out neighbor))
{
neighbor = new NodeData
Expand All @@ -127,6 +134,7 @@ public void Execute()
continue;
}

// This neighbour has a lower cost
if (newG < neighbor.G)
{
neighbor.G = newG;
Expand Down Expand Up @@ -167,5 +175,23 @@ private void RetracePath(NodeData startNode, NativeHashMap<int, NodeData> closed
currentNode = closedSet[currentNode.ParentIndex];
}
}

private bool HasUnresolvableCondition(int currentIndex)
{
foreach (var conditionIndex in this.NodeConditions.GetValuesForKey(currentIndex))
{
if (this.RunData.ConditionsMet[conditionIndex])
{
continue;
}

if (!this.ConditionConnections.GetValuesForKey(conditionIndex).MoveNext())
{
return true;
}
}

return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -485,5 +485,69 @@ public void Resolve_ShouldNotResolve_CompletedCondition()
result.Should().HaveCount(2);
result.Should().Equal(incompleteAction, rootAction);
}

[Test]
public void Resolve_ShouldNotResolve_ActionWithFalseConditionWithoutConnections()
{
var rootConnection = new TestConnection("Root");
var availableConnection = new TestConnection("Available");
var unavailableConnection = new TestConnection("Unavailable");

var goal = new TestAction("goal")
{
Conditions = new ICondition[] { rootConnection }
};

var expensiveAction = new TestAction("expensiveAction")
{
Effects = new IEffect[] { rootConnection },
};

var unavailableAction = new TestAction("subAction")
{
Effects = new IEffect[] { rootConnection },
Conditions = new ICondition[] { unavailableConnection, availableConnection }
};

var shouldNotResolveAction = new TestAction("shouldNotResolveAction")
{
Effects = new IEffect[] { availableConnection },
};

var actions = new IAction[] { goal, expensiveAction, unavailableAction, shouldNotResolveAction };
var resolver = new GraphResolver(actions, new TestKeyResolver());

var executableBuilder = resolver.GetExecutableBuilder();
executableBuilder
.SetExecutable(expensiveAction, true)
.SetExecutable(unavailableAction, false)
.SetExecutable(shouldNotResolveAction, true);

var positionBuilder = resolver.GetPositionBuilder();
var costBuilder = resolver.GetCostBuilder();
costBuilder.SetCost(expensiveAction, 100f);

var conditionBuilder = resolver.GetConditionBuilder();

// Act
var handle = resolver.StartResolve(new RunData
{
StartIndex = 0,
IsExecutable = new NativeArray<bool>(executableBuilder.Build(), Allocator.TempJob),
Positions = new NativeArray<float3>(positionBuilder.Build(), Allocator.TempJob),
Costs = new NativeArray<float>(costBuilder.Build(), Allocator.TempJob),
ConditionsMet = new NativeArray<bool>(conditionBuilder.Build(), Allocator.TempJob),
DistanceMultiplier = 1f
});

var result = handle.Complete();

// Cleanup
resolver.Dispose();

// Assert
result.Should().HaveCount(1);
result.Should().Equal(expensiveAction);
}
}
}
Loading