/** * Performs the actual search. */ IPath::SearchResult CPathEstimator::DoSearch(const MoveData& moveData, const CPathFinderDef& peDef) { bool foundGoal = false; while (!openBlocks.empty() && (openBlockBufferIndex < maxBlocksToBeSearched)) { // get the open block with lowest cost OpenBlock* ob = openBlocks.top(); openBlocks.pop(); // check if the block has been marked as unaccessible during its time in the queue if (blockState[ob->blocknr].options & (PATHOPT_BLOCKED | PATHOPT_CLOSED | PATHOPT_FORBIDDEN)) continue; // no, check if the goal is already reached int xBSquare = blockState[ob->blocknr].sqrCenter[moveData.pathType].x; int zBSquare = blockState[ob->blocknr].sqrCenter[moveData.pathType].y; int xGSquare = ob->block.x * BLOCK_SIZE + goalSqrOffset.x; int zGSquare = ob->block.y * BLOCK_SIZE + goalSqrOffset.y; if (peDef.IsGoal(xBSquare, zBSquare) || peDef.IsGoal(xGSquare, zGSquare)) { goalBlock = ob->block; goalHeuristic = 0; foundGoal = true; break; } // no, test the 8 surrounding blocks // NOTE: each of these calls increments openBlockBufferIndex by 1, so // maxBlocksToBeSearched is always less than <MAX_SEARCHED_BLOCKS - 8> TestBlock(moveData, peDef, *ob, PATHDIR_LEFT); TestBlock(moveData, peDef, *ob, PATHDIR_LEFT_UP); TestBlock(moveData, peDef, *ob, PATHDIR_UP); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT_UP); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT_DOWN); TestBlock(moveData, peDef, *ob, PATHDIR_DOWN); TestBlock(moveData, peDef, *ob, PATHDIR_LEFT_DOWN); // mark this block as closed blockState[ob->blocknr].options |= PATHOPT_CLOSED; } // we found our goal if (foundGoal) return Ok; // we could not reach the goal if (openBlockBufferIndex >= maxBlocksToBeSearched) return GoalOutOfRange; // search could not reach the goal due to the unit being locked in if (openBlocks.empty()) return GoalOutOfRange; // should never happen LogObject() << "ERROR: CPathEstimator::DoSearch() - Unhandled end of search!\n"; return Error; }
/** * Performs the actual search. */ IPath::SearchResult CPathEstimator::DoSearch(const MoveData& moveData, const CPathFinderDef& peDef, bool synced) { bool foundGoal = false; while (!openBlocks.empty() && (openBlockBuffer.GetSize() < maxBlocksToBeSearched)) { // get the open block with lowest cost PathNode* ob = const_cast<PathNode*>(openBlocks.top()); openBlocks.pop(); // check if the block has been marked as unaccessible during its time in the queue if (blockStates[ob->nodeNum].nodeMask & (PATHOPT_BLOCKED | PATHOPT_CLOSED | PATHOPT_FORBIDDEN)) continue; // no, check if the goal is already reached const int xBSquare = blockStates[ob->nodeNum].nodeOffsets[moveData.pathType].x; const int zBSquare = blockStates[ob->nodeNum].nodeOffsets[moveData.pathType].y; const int xGSquare = ob->nodePos.x * BLOCK_SIZE + goalSqrOffset.x; const int zGSquare = ob->nodePos.y * BLOCK_SIZE + goalSqrOffset.y; if (peDef.IsGoal(xBSquare, zBSquare) || peDef.IsGoal(xGSquare, zGSquare)) { goalBlock = ob->nodePos; goalHeuristic = 0; foundGoal = true; break; } // no, test the 8 surrounding blocks // NOTE: each of these calls increments openBlockBuffer.idx by 1, so // maxBlocksToBeSearched is always less than <MAX_SEARCHED_NODES_PE - 8> TestBlock(moveData, peDef, *ob, PATHDIR_LEFT, synced); TestBlock(moveData, peDef, *ob, PATHDIR_LEFT_UP, synced); TestBlock(moveData, peDef, *ob, PATHDIR_UP, synced); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT_UP, synced); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT, synced); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT_DOWN, synced); TestBlock(moveData, peDef, *ob, PATHDIR_DOWN, synced); TestBlock(moveData, peDef, *ob, PATHDIR_LEFT_DOWN, synced); // mark this block as closed blockStates[ob->nodeNum].nodeMask |= PATHOPT_CLOSED; } // we found our goal if (foundGoal) return IPath::Ok; // we could not reach the goal if (openBlockBuffer.GetSize() >= maxBlocksToBeSearched) return IPath::GoalOutOfRange; // search could not reach the goal due to the unit being locked in if (openBlocks.empty()) return IPath::GoalOutOfRange; // should never happen LogObject() << "ERROR: CPathEstimator::DoSearch() - Unhandled end of search!\n"; return IPath::Error; }
/* Performs the actual search. */ IPath::SearchResult CPathEstimator::DoSearch(const MoveData& moveData, const CPathFinderDef& peDef) { bool foundGoal = false; while(!openBlocks.empty() && (openBlockBufferPointer - openBlockBuffer) < (maxBlocksToBeSearched - 8)) { //Get the open block with lowest cost. OpenBlock* ob = openBlocks.top(); openBlocks.pop(); //Check if the block has been marked as unaccessable during it's time in queue. if(blockState[ob->blocknr].options & (PATHOPT_BLOCKED | PATHOPT_CLOSED | PATHOPT_FORBIDDEN)) continue; //Check if the goal is reached. int xBSquare = blockState[ob->blocknr].sqrCenter[moveData.pathType].x; int zBSquare = blockState[ob->blocknr].sqrCenter[moveData.pathType].y; int xGSquare = ob->block.x * BLOCK_SIZE + goalSqrOffset.x; int zGSquare = ob->block.y * BLOCK_SIZE + goalSqrOffset.y; if(peDef.IsGoal(xBSquare, zBSquare) || peDef.IsGoal(xGSquare, zGSquare)) { goalBlock = ob->block; goalHeuristic = 0; foundGoal = true; break; } //Test the 8 surrounding blocks. TestBlock(moveData, peDef, *ob, PATHDIR_LEFT); TestBlock(moveData, peDef, *ob, PATHDIR_LEFT_UP); TestBlock(moveData, peDef, *ob, PATHDIR_UP); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT_UP); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT); TestBlock(moveData, peDef, *ob, PATHDIR_RIGHT_DOWN); TestBlock(moveData, peDef, *ob, PATHDIR_DOWN); TestBlock(moveData, peDef, *ob, PATHDIR_LEFT_DOWN); //Mark this block as closed. blockState[ob->blocknr].options |= PATHOPT_CLOSED; } //Returning search-result. if(foundGoal) return Ok; //Could not reach the goal. if(openBlockBufferPointer - openBlockBuffer >= (maxBlocksToBeSearched - 8)) return GoalOutOfRange; //Search could not reach the goal, due to the unit being locked in. if(openBlocks.empty()) return GoalOutOfRange; //Below shall never be runned. logOutput << "ERROR: CPathEstimator::DoSearch() - Unhandled end of search!\n"; return Error; }
/* Performs the actual search. */ IPath::SearchResult CPathFinder::DoSearch(const MoveData& moveData, const CPathFinderDef& pfDef) { bool foundGoal = false; while(!openSquares.empty() && openSquareBufferPointer - openSquareBuffer < (maxNodesToBeSearched - 8)) { //Gets the open square with lowest expected path-cost. OpenSquare* os = openSquares.top(); openSquares.pop(); //Check if this OpenSquare-holder have become obsolete. if(squareState[os->sqr].cost != os->cost) continue; //Check if the goal is reached. if(pfDef.IsGoal(os->square.x, os->square.y)) { goalSquare = os->sqr; goalHeuristic = 0; foundGoal = true; break; } //Testing the 8 surrounding squares. bool right=TestSquare(moveData, pfDef, os, PATHOPT_RIGHT); bool left=TestSquare(moveData, pfDef, os, PATHOPT_LEFT); bool up=TestSquare(moveData, pfDef, os, PATHOPT_UP); bool down=TestSquare(moveData, pfDef, os, PATHOPT_DOWN); if(up) { //we dont want to search diagonally if there is a blocking object (not blocking terrain) in one of the two side squares if(right) TestSquare(moveData, pfDef, os, (PATHOPT_RIGHT | PATHOPT_UP)); if(left) TestSquare(moveData, pfDef, os, (PATHOPT_LEFT | PATHOPT_UP)); } if(down) { if(right) TestSquare(moveData, pfDef, os, (PATHOPT_RIGHT | PATHOPT_DOWN)); if(left) TestSquare(moveData, pfDef, os, (PATHOPT_LEFT | PATHOPT_DOWN)); } //Mark this square as closed. squareState[os->sqr].status |= PATHOPT_CLOSED; } //Returning search-result. if(foundGoal) return Ok; //Could not reach the goal. if(openSquareBufferPointer - openSquareBuffer >= (maxNodesToBeSearched - 8)) return GoalOutOfRange; //Search could not reach the goal, due to the unit being locked in. if(openSquares.empty()) return GoalOutOfRange; //Below shall never be runned. *info << "ERROR: CPathFinder::DoSearch() - Unhandled end of search!\n"; return Error; }
IPath::SearchResult CPathFinder::InitSearch(const MoveDef& moveDef, const CPathFinderDef& pfDef, const CSolidObject* owner, bool synced) { // If exact path is reqired and the goal is blocked, then no search is needed. if (exactPath && pfDef.GoalIsBlocked(moveDef, CMoveMath::BLOCK_STRUCTURE, owner)) return IPath::CantGetCloser; // Clamp the start position if (startxSqr >= gs->mapx) { startxSqr = gs->mapxm1; } if (startzSqr >= gs->mapy) { startzSqr = gs->mapym1; } const bool isStartGoal = pfDef.IsGoal(startxSqr, startzSqr); // although our starting square may be inside the goal radius, the starting coordinate may be outside. // in this case we do not want to return CantGetCloser, but instead a path to our starting square. if (isStartGoal && pfDef.startInGoalRadius) return IPath::CantGetCloser; // Clear the system from last search. ResetSearch(); // Marks and store the start-square. squareStates.nodeMask[mStartSquareIdx] = (PATHOPT_START | PATHOPT_OPEN); squareStates.fCost[mStartSquareIdx] = 0.0f; squareStates.gCost[mStartSquareIdx] = 0.0f; squareStates.SetMaxCost(NODE_COST_F, 0.0f); squareStates.SetMaxCost(NODE_COST_G, 0.0f); dirtySquares.push_back(mStartSquareIdx); // Make the beginning the fest square found. mGoalSquareIdx = mStartSquareIdx; mGoalHeuristic = pfDef.Heuristic(startxSqr, startzSqr); // Adding the start-square to the queue. openSquareBuffer.SetSize(0); PathNode* os = openSquareBuffer.GetNode(openSquareBuffer.GetSize()); os->fCost = 0.0f; os->gCost = 0.0f; os->nodePos.x = startxSqr; os->nodePos.y = startzSqr; os->nodeNum = mStartSquareIdx; openSquares.push(os); // perform the search IPath::SearchResult result = DoSearch(moveDef, pfDef, owner, synced); // if no improvements are found, then return CantGetCloser instead if ((mGoalSquareIdx == mStartSquareIdx && (!isStartGoal || pfDef.startInGoalRadius)) || mGoalSquareIdx == 0) { return IPath::CantGetCloser; } return result; }
/** * Performs the actual search. */ IPath::SearchResult CPathFinder::DoSearch(const MoveData& moveData, const CPathFinderDef& pfDef, int ownerId, bool synced) { bool foundGoal = false; while (!openSquares.empty() && (openSquareBuffer.GetSize() < maxSquaresToBeSearched)) { // Get the open square with lowest expected path-cost. PathNode* os = const_cast<PathNode*>(openSquares.top()); openSquares.pop(); // check if this PathNode has become obsolete if (squareStates[os->nodeNum].fCost != os->fCost) continue; // Check if the goal is reached. if (pfDef.IsGoal(os->nodePos.x, os->nodePos.y)) { goalSquare = os->nodeNum; goalHeuristic = 0; foundGoal = true; break; } // Test the 8 surrounding squares. const bool right = TestSquare(moveData, pfDef, os, PATHOPT_RIGHT, ownerId, synced); const bool left = TestSquare(moveData, pfDef, os, PATHOPT_LEFT, ownerId, synced); const bool up = TestSquare(moveData, pfDef, os, PATHOPT_UP, ownerId, synced); const bool down = TestSquare(moveData, pfDef, os, PATHOPT_DOWN, ownerId, synced); if (up) { // we dont want to search diagonally if there is a blocking object // (not blocking terrain) in one of the two side squares if (right) { TestSquare(moveData, pfDef, os, (PATHOPT_RIGHT | PATHOPT_UP), ownerId, synced); } if (left) { TestSquare(moveData, pfDef, os, (PATHOPT_LEFT | PATHOPT_UP), ownerId, synced); } } if (down) { if (right) { TestSquare(moveData, pfDef, os, (PATHOPT_RIGHT | PATHOPT_DOWN), ownerId, synced); } if (left) { TestSquare(moveData, pfDef, os, (PATHOPT_LEFT | PATHOPT_DOWN), ownerId, synced); } } // Mark this square as closed. squareStates[os->nodeNum].nodeMask |= PATHOPT_CLOSED; } if (foundGoal) return IPath::Ok; // Could not reach the goal. if (openSquareBuffer.GetSize() >= maxSquaresToBeSearched) return IPath::GoalOutOfRange; // Search could not reach the goal, due to the unit being locked in. if (openSquares.empty()) return IPath::GoalOutOfRange; // Below shall never be runned. LogObject() << "ERROR: CPathFinder::DoSearch() - Unhandled end of search!\n"; return IPath::Error; }
// set up the starting point of the search IPath::SearchResult IPathFinder::InitSearch(const MoveDef& moveDef, const CPathFinderDef& pfDef, const CSolidObject* owner) { int2 square = mStartBlock; if (isEstimator) square = blockStates.peNodeOffsets[moveDef.pathType][mStartBlockIdx]; const bool isStartGoal = pfDef.IsGoal(square.x, square.y); const bool startInGoal = pfDef.startInGoalRadius; // although our starting square may be inside the goal radius, the starting coordinate may be outside. // in this case we do not want to return CantGetCloser, but instead a path to our starting square. if (isStartGoal && startInGoal) return IPath::CantGetCloser; // no, clean the system from last search ResetSearch(); // mark and store the start-block blockStates.nodeMask[mStartBlockIdx] &= PATHOPT_OBSOLETE; // clear all except PATHOPT_OBSOLETE blockStates.nodeMask[mStartBlockIdx] |= PATHOPT_OPEN; blockStates.fCost[mStartBlockIdx] = 0.0f; blockStates.gCost[mStartBlockIdx] = 0.0f; blockStates.SetMaxCost(NODE_COST_F, 0.0f); blockStates.SetMaxCost(NODE_COST_G, 0.0f); dirtyBlocks.push_back(mStartBlockIdx); // start a new search and // add the starting block to the open-blocks-queue openBlockBuffer.SetSize(0); PathNode* ob = openBlockBuffer.GetNode(openBlockBuffer.GetSize()); ob->fCost = 0.0f; ob->gCost = 0.0f; ob->nodePos = mStartBlock; ob->nodeNum = mStartBlockIdx; openBlocks.push(ob); // mark starting point as best found position mGoalBlockIdx = mStartBlockIdx; mGoalHeuristic = pfDef.Heuristic(square.x, square.y); // perform the search const IPath::SearchResult result = DoSearch(moveDef, pfDef, owner); if (result == IPath::Ok) return result; if (mGoalBlockIdx != mStartBlockIdx) return result; // if start and goal are within the same block, but distinct squares // or considered a single point for search purposes, then we probably // can not get closer return (!isStartGoal || startInGoal)? IPath::CantGetCloser: result; }
// set up the starting point of the search IPath::SearchResult CPathFinder::InitSearch(const MoveData& moveData, const CPathFinderDef& pfDef, int ownerId, bool synced) { // If exact path is reqired and the goal is blocked, then no search is needed. if (exactPath && pfDef.GoalIsBlocked(moveData, (CMoveMath::BLOCK_STRUCTURE | CMoveMath::BLOCK_TERRAIN))) return IPath::CantGetCloser; // Clamp the start position if (startxSqr < 0) { startxSqr = 0; } if (startxSqr >= gs->mapx) { startxSqr = gs->mapx - 1; } if (startzSqr < 0) { startzSqr = 0; } if (startzSqr >= gs->mapy) { startzSqr = gs->mapy - 1; } // If the starting position is a goal position, then no search need to be performed. if (pfDef.IsGoal(startxSqr, startzSqr)) return IPath::CantGetCloser; // Clear the system from last search. ResetSearch(); // Marks and store the start-square. squareStates[startSquare].nodeMask = (PATHOPT_START | PATHOPT_OPEN); squareStates[startSquare].fCost = 0.0f; squareStates[startSquare].gCost = 0.0f; squareStates.SetMaxFCost(0.0f); squareStates.SetMaxGCost(0.0f); dirtySquares.push_back(startSquare); // Make the beginning the fest square found. goalSquare = startSquare; goalHeuristic = pfDef.Heuristic(startxSqr, startzSqr); // Adding the start-square to the queue. openSquareBuffer.SetSize(0); PathNode* os = openSquareBuffer.GetNode(openSquareBuffer.GetSize()); os->fCost = 0.0f; os->gCost = 0.0f; os->nodePos.x = startxSqr; os->nodePos.y = startzSqr; os->nodeNum = startSquare; openSquares.push(os); // perform the search IPath::SearchResult result = DoSearch(moveData, pfDef, ownerId, synced); // if no improvements are found, then return CantGetCloser instead if (goalSquare == startSquare || goalSquare == 0) { return IPath::CantGetCloser; } return result; }
// set up the starting point of the search IPath::SearchResult CPathEstimator::InitSearch(const MoveData& moveData, const CPathFinderDef& peDef, bool synced) { // is starting square inside goal area? const int xSquare = blockStates[startBlocknr].nodeOffsets[moveData.pathType].x; const int zSquare = blockStates[startBlocknr].nodeOffsets[moveData.pathType].y; if (peDef.IsGoal(xSquare, zSquare)) return IPath::CantGetCloser; // no, clean the system from last search ResetSearch(); // mark and store the start-block blockStates[startBlocknr].nodeMask |= PATHOPT_OPEN; blockStates[startBlocknr].fCost = 0.0f; blockStates[startBlocknr].gCost = 0.0f; blockStates.SetMaxFCost(0.0f); blockStates.SetMaxGCost(0.0f); dirtyBlocks.push_back(startBlocknr); openBlockBuffer.SetSize(0); // add the starting block to the open-blocks-queue PathNode* ob = openBlockBuffer.GetNode(openBlockBuffer.GetSize()); ob->fCost = 0.0f; ob->gCost = 0.0f; ob->nodePos = startBlock; ob->nodeNum = startBlocknr; openBlocks.push(ob); // mark starting point as best found position goalBlock = startBlock; goalHeuristic = peDef.Heuristic(xSquare, zSquare); // get the goal square offset goalSqrOffset = peDef.GoalSquareOffset(BLOCK_SIZE); // perform the search IPath::SearchResult result = DoSearch(moveData, peDef, synced); // if no improvements are found, then return CantGetCloser instead if (goalBlock.x == startBlock.x && goalBlock.y == startBlock.y) { return IPath::CantGetCloser; } return result; }
/* Setting up the starting point of the search. */ IPath::SearchResult CPathFinder::InitSearch(const MoveData& moveData, const CPathFinderDef& pfDef) { //If exact path is reqired and the goal is blocked, then no search is needed. if(exactPath && pfDef.GoalIsBlocked(moveData, (CMoveMath::BLOCK_STRUCTURE | CMoveMath::BLOCK_TERRAIN))) return CantGetCloser; //Clamp the start position if (startxSqr < 0) startxSqr=0; if (startxSqr >= gs->mapx) startxSqr = gs->mapx-1; if (startzSqr < 0) startzSqr =0; if (startzSqr >= gs->mapy) startzSqr = gs->mapy-1; //If the starting position is a goal position, then no search need to be performed. if(pfDef.IsGoal(startxSqr, startzSqr)) return CantGetCloser; //Clearing the system from last search. ResetSearch(); //Marks and store the start-square. squareState[startSquare].status = (PATHOPT_START | PATHOPT_OPEN); squareState[startSquare].cost = 0; dirtySquares.push_back(startSquare); //Make the beginning the fest square found. goalSquare = startSquare; goalHeuristic = pfDef.Heuristic(startxSqr, startzSqr); //Adding the start-square to the queue. openSquareBufferPointer = &openSquareBuffer[0]; OpenSquare *os = openSquareBufferPointer; //Taking first OpenSquare in buffer. os->currentCost = 0; os->cost = 0; os->square.x = startxSqr; os->square.y = startzSqr; os->sqr = startSquare; openSquares.push(os); //Performs the search. SearchResult result = DoSearch(moveData, pfDef); //If no improvement has been found then return CantGetCloser instead. if(goalSquare == startSquare || goalSquare == 0) { return CantGetCloser; } else return result; }
IPath::SearchResult CPathFinder::DoSearch( const MoveDef& moveDef, const CPathFinderDef& pfDef, const CSolidObject* owner ) { bool foundGoal = false; while (!openBlocks.empty() && (openBlockBuffer.GetSize() < maxBlocksToBeSearched)) { // Get the open square with lowest expected path-cost. PathNode* openSquare = const_cast<PathNode*>(openBlocks.top()); openBlocks.pop(); // check if this PathNode has become obsolete if (blockStates.fCost[openSquare->nodeNum] != openSquare->fCost) continue; // Check if the goal is reached. if (pfDef.IsGoal(openSquare->nodePos.x, openSquare->nodePos.y)) { mGoalBlockIdx = openSquare->nodeNum; mGoalHeuristic = 0.0f; foundGoal = true; break; } TestNeighborSquares(moveDef, pfDef, openSquare, owner); } if (foundGoal) return IPath::Ok; // could not reach goal within <maxBlocksToBeSearched> exploration limit if (openBlockBuffer.GetSize() >= maxBlocksToBeSearched) return IPath::GoalOutOfRange; // could not reach goal from this starting position if nothing to left to explore if (openBlocks.empty()) return IPath::GoalOutOfRange; // should be unreachable return IPath::Error; }
/** * Make some initial calculations and preparations */ IPath::SearchResult CPathEstimator::InitSearch(const MoveData& moveData, const CPathFinderDef& peDef) { // is starting square inside goal area? int xSquare = blockState[startBlocknr].sqrCenter[moveData.pathType].x; int zSquare = blockState[startBlocknr].sqrCenter[moveData.pathType].y; if (peDef.IsGoal(xSquare, zSquare)) return CantGetCloser; // no, clean the system from last search ResetSearch(); // mark and store the start-block blockState[startBlocknr].options |= PATHOPT_OPEN; blockState[startBlocknr].cost = 0; dirtyBlocks.push_back(startBlocknr); openBlockBufferIndex = 0; // add the starting block to the open-blocks-queue OpenBlock* ob = &openBlockBuffer[openBlockBufferIndex]; ob->cost = 0; ob->currentCost = 0; ob->block = startBlock; ob->blocknr = startBlocknr; openBlocks.push(ob); // mark starting point as best found position goalBlock = startBlock; goalHeuristic = peDef.Heuristic(xSquare, zSquare); // get the goal square offset goalSqrOffset = peDef.GoalSquareOffset(BLOCK_SIZE); // perform the search SearchResult result = DoSearch(moveData, peDef); // if no improvements are found, then return CantGetCloser instead if (goalBlock.x == startBlock.x && goalBlock.y == startBlock.y) return CantGetCloser; else return result; }
/* Making some initial calculations and preparations. */ IPath::SearchResult CPathEstimator::InitSearch(const MoveData& moveData, const CPathFinderDef& peDef) { //Starting square is inside goal area? int xSquare = blockState[startBlocknr].sqrCenter[moveData.pathType].x; int zSquare = blockState[startBlocknr].sqrCenter[moveData.pathType].y; if(peDef.IsGoal(xSquare, zSquare)) return CantGetCloser; //Cleaning the system from last search. ResetSearch(); //Marks and store the start-block. blockState[startBlocknr].options |= PATHOPT_OPEN; blockState[startBlocknr].cost = 0; dirtyBlocks.push_back(startBlocknr); //Adding the starting block to the open-blocks-queue. OpenBlock* ob = openBlockBufferPointer = openBlockBuffer; ob->cost = 0; ob->currentCost = 0; ob->block = startBlock; ob->blocknr = startBlocknr; openBlocks.push(ob); //Mark starting point as best found position. goalBlock = startBlock; goalHeuristic = peDef.Heuristic(xSquare, zSquare); //Gets goal square offset. goalSqrOffset = peDef.GoalSquareOffset(BLOCK_SIZE); //Performs the search. SearchResult result = DoSearch(moveData, peDef); //If no improvements are found, then return CantGetCloser instead. if(goalBlock.x == startBlock.x && goalBlock.y == startBlock.y) return CantGetCloser; else return result; }
/** * Search with several start positions */ IPath::SearchResult CPathFinder::GetPath( const MoveData& moveData, const std::vector<float3>& startPos, const CPathFinderDef& pfDef, IPath::Path& path, int ownerId, bool synced ) { // Clear the given path. path.path.clear(); path.squares.clear(); path.pathCost = PATHCOST_INFINITY; // Store som basic data. maxSquaresToBeSearched = MAX_SEARCHED_NODES_PF - 8U; testMobile = false; exactPath = true; needPath = true; // If exact path is reqired and the goal is blocked, then no search is needed. if (exactPath && pfDef.GoalIsBlocked(moveData, (CMoveMath::BLOCK_STRUCTURE | CMoveMath::BLOCK_TERRAIN))) return IPath::CantGetCloser; // If the starting position is a goal position, then no search need to be performed. if (pfDef.IsGoal(startxSqr, startzSqr)) return IPath::CantGetCloser; // Clearing the system from last search. ResetSearch(); openSquareBuffer.SetSize(0); for (std::vector<float3>::const_iterator si = startPos.begin(); si != startPos.end(); ++si) { start = *si; startxSqr = (int(start.x) / SQUARE_SIZE) | 1; startzSqr = (int(start.z) / SQUARE_SIZE) | 1; startSquare = startxSqr + startzSqr * gs->mapx; goalSquare = startSquare; squareStates[startSquare].nodeMask = (PATHOPT_START | PATHOPT_OPEN); squareStates[startSquare].fCost = 0.0f; squareStates[startSquare].gCost = 0.0f; dirtySquares.push_back(startSquare); if (openSquareBuffer.GetSize() >= MAX_SEARCHED_NODES_PF) { continue; } PathNode* os = openSquareBuffer.GetNode(openSquareBuffer.GetSize()); os->fCost = 0.0f; os->gCost = 0.0f; os->nodePos.x = startxSqr; os->nodePos.y = startzSqr; os->nodeNum = startSquare; openSquareBuffer.SetSize(openSquareBuffer.GetSize() + 1); openSquares.push(os); } // note: DoSearch, not InitSearch IPath::SearchResult result = DoSearch(moveData, pfDef, ownerId, synced); // Respond to the success of the search. if (result == IPath::Ok) { FinishSearch(moveData, path); if (PATHDEBUG) { LogObject() << "Path found.\n"; LogObject() << "Nodes tested: " << testedNodes << "\n"; LogObject() << "Open squares: " << openSquareBuffer.GetSize() << "\n"; LogObject() << "Path nodes: " << path.path.size() << "\n"; LogObject() << "Path cost: " << path.pathCost << "\n"; } } else { if (PATHDEBUG) { LogObject() << "No path found!\n"; LogObject() << "Nodes tested: " << testedNodes << "\n"; LogObject() << "Open squares: " << openSquareBuffer.GetSize() << "\n"; } } return result; }
/* Search with several start positions */ IPath::SearchResult CPathFinder::GetPath(const MoveData& moveData, std::vector<float3> startPos, const CPathFinderDef& pfDef, Path& path) { //Clear the given path. path.path.clear(); path.pathCost = PATHCOST_INFINITY; //Store som basic data. maxNodesToBeSearched = MAX_SEARCHED_SQARES; testMobile=false; exactPath = true; needPath=true; //If exact path is reqired and the goal is blocked, then no search is needed. if(exactPath && pfDef.GoalIsBlocked(moveData, (CMoveMath::BLOCK_STRUCTURE | CMoveMath::BLOCK_TERRAIN))) return CantGetCloser; //If the starting position is a goal position, then no search need to be performed. if(pfDef.IsGoal(startxSqr, startzSqr)) return CantGetCloser; //Clearing the system from last search. ResetSearch(); openSquareBufferPointer = &openSquareBuffer[0]; for(std::vector<float3>::iterator si=startPos.begin(); si!=startPos.end(); ++si) { start = *si; startxSqr = (int(start.x) / SQUARE_SIZE)|1; startzSqr = (int(start.z) / SQUARE_SIZE)|1; startSquare = startxSqr + startzSqr * gs->mapx; squareState[startSquare].status = (PATHOPT_START | PATHOPT_OPEN); squareState[startSquare].cost = 0; dirtySquares.push_back(startSquare); goalSquare = startSquare; OpenSquare *os = ++openSquareBufferPointer; //Taking first OpenSquare in buffer. os->currentCost = 0; os->cost = 0; os->square.x = startxSqr; os->square.y = startzSqr; os->sqr = startSquare; openSquares.push(os); } //Performs the search. SearchResult result = DoSearch(moveData, pfDef); //Respond to the success of the search. if(result == Ok) { FinishSearch(moveData, path); if(PATHDEBUG) { *info << "Path found.\n"; *info << "Nodes tested: " << (int)testedNodes << "\n"; *info << "Open squares: " << (openSquareBufferPointer - openSquareBuffer) << "\n"; *info << "Path steps: " << (int)(path.path.size()) << "\n"; *info << "Path cost: " << path.pathCost << "\n"; } } else { if(PATHDEBUG) { *info << "Path not found!\n"; *info << "Nodes tested: " << (int)testedNodes << "\n"; *info << "Open squares: " << (openSquareBufferPointer - openSquareBuffer) << "\n"; } } return result; }
// set up the starting point of the search IPath::SearchResult IPathFinder::InitSearch(const MoveDef& moveDef, const CPathFinderDef& pfDef, const CSolidObject* owner) { int2 square = mStartBlock; if (BLOCK_SIZE != 1) square = blockStates.peNodeOffsets[moveDef.pathType][mStartBlockIdx]; const bool isStartGoal = pfDef.IsGoal(square.x, square.y); const bool startInGoal = pfDef.startInGoalRadius; const bool allowRawPath = pfDef.allowRawPath; const bool allowDefPath = pfDef.allowDefPath; assert(allowRawPath || allowDefPath); // cleanup after the last search ResetSearch(); IPath::SearchResult results[] = {IPath::CantGetCloser, IPath::Ok, IPath::CantGetCloser}; // although our starting square may be inside the goal radius, the starting coordinate may be outside. // in this case we do not want to return CantGetCloser, but instead a path to our starting square. if (isStartGoal && startInGoal) return results[allowRawPath]; // mark and store the start-block; clear all bits except PATHOPT_OBSOLETE blockStates.nodeMask[mStartBlockIdx] &= PATHOPT_OBSOLETE; blockStates.nodeMask[mStartBlockIdx] |= PATHOPT_OPEN; blockStates.fCost[mStartBlockIdx] = 0.0f; blockStates.gCost[mStartBlockIdx] = 0.0f; blockStates.SetMaxCost(NODE_COST_F, 0.0f); blockStates.SetMaxCost(NODE_COST_G, 0.0f); dirtyBlocks.push_back(mStartBlockIdx); // start a new search and add the starting block to the open-blocks-queue openBlockBuffer.SetSize(0); PathNode* ob = openBlockBuffer.GetNode(openBlockBuffer.GetSize()); ob->fCost = 0.0f; ob->gCost = 0.0f; ob->nodePos = mStartBlock; ob->nodeNum = mStartBlockIdx; openBlocks.push(ob); // mark starting point as best found position mGoalHeuristic = pfDef.Heuristic(square.x, square.y, BLOCK_SIZE); enum { RAW = 0, IPF = 1, }; // perform the search results[RAW] = (allowRawPath )? DoRawSearch(moveDef, pfDef, owner): IPath::Error; results[IPF] = (allowDefPath && results[RAW] == IPath::Error)? DoSearch(moveDef, pfDef, owner): results[RAW]; if (results[IPF] == IPath::Ok) return IPath::Ok; if (mGoalBlockIdx != mStartBlockIdx) return results[IPF]; // if start and goal are within the same block but distinct squares (or // considered a single point for search purposes), then we probably can // not get closer and should return CGC *unless* the caller requested a // raw search only return results[IPF + ((!allowRawPath || allowDefPath) && (!isStartGoal || startInGoal))]; }