Made A-star cost admissible, fixed previous visib bug, commented path finder code, rearranged tests for readability.

This commit is contained in:
Mikko Mononen 2010-02-16 18:43:04 +00:00
parent 095c9a544f
commit e51b31dab4

View File

@ -1121,7 +1121,7 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
m_nodePool->clear(); m_nodePool->clear();
m_openList->clear(); m_openList->clear();
static const float H_SCALE = 1.1f; // Heuristic scale. static const float H_SCALE = 0.999f; // Heuristic scale.
dtNode* startNode = m_nodePool->getNode(startRef); dtNode* startNode = m_nodePool->getNode(startRef);
startNode->pidx = 0; startNode->pidx = 0;
@ -1139,7 +1139,11 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
while (!m_openList->empty()) while (!m_openList->empty())
{ {
dtNode* bestNode = m_openList->pop(); dtNode* bestNode = m_openList->pop();
// Remove node from open list and put it in closed list.
bestNode->flags &= ~DT_NODE_OPEN;
bestNode->flags |= DT_NODE_CLOSED;
// Reached the goal, stop searching.
if (bestNode->id == endRef) if (bestNode->id == endRef)
{ {
lastBestNode = bestNode; lastBestNode = bestNode;
@ -1180,8 +1184,9 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestHeader->links[i].next) for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestHeader->links[i].next)
{ {
dtPolyRef neighbourRef = bestHeader->links[i].ref; dtPolyRef neighbourRef = bestHeader->links[i].ref;
// Skip invalid ids and do not expand back to parent node.
if (!neighbourRef || parentRef == neighbourRef) // Skip invalid ids and do not expand back to where we came from.
if (!neighbourRef || neighbourRef == bestRef)
continue; continue;
// Get neighbour poly and tile. // Get neighbour poly and tile.
@ -1228,34 +1233,39 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
dtNode* actualNode = m_nodePool->getNode(newNode.id); dtNode* actualNode = m_nodePool->getNode(newNode.id);
if (!actualNode) if (!actualNode)
continue; continue;
if (!((actualNode->flags & DT_NODE_OPEN) && newNode.total > actualNode->total) && // The node is already in open list and the new result is worse, skip.
!((actualNode->flags & DT_NODE_CLOSED) && newNode.total > actualNode->total)) if ((actualNode->flags & DT_NODE_OPEN) && newNode.total >= actualNode->total)
continue;
// The node is already visited and process, and the new result is worse, skip.
if ((actualNode->flags & DT_NODE_CLOSED) && newNode.total >= actualNode->total)
continue;
// Add or update the node.
actualNode->flags &= ~DT_NODE_CLOSED;
actualNode->pidx = newNode.pidx;
actualNode->cost = newNode.cost;
actualNode->total = newNode.total;
// Update nearest node to target so far.
if (h < lastBestNodeCost)
{ {
actualNode->flags &= ~DT_NODE_CLOSED; lastBestNodeCost = h;
actualNode->pidx = newNode.pidx; lastBestNode = actualNode;
actualNode->cost = newNode.cost; }
actualNode->total = newNode.total;
if (h < lastBestNodeCost) if (actualNode->flags & DT_NODE_OPEN)
{ {
lastBestNodeCost = h; // Already in open, update node location.
lastBestNode = actualNode; m_openList->modify(actualNode);
} }
else
if (actualNode->flags & DT_NODE_OPEN) {
{ // Put the node in open list.
m_openList->modify(actualNode); actualNode->flags |= DT_NODE_OPEN;
} m_openList->push(actualNode);
else
{
actualNode->flags |= DT_NODE_OPEN;
m_openList->push(actualNode);
}
} }
} }
bestNode->flags |= DT_NODE_CLOSED;
} }
// Reverse the path. // Reverse the path.