HWND CFindPanel::CreatePane(HWND hParent, int nBarHeight) { ResetSearch(); if (mh_Pane && IsWindow(mh_Pane)) return mh_Pane; if (!RegisterPaneClass()) return NULL; _ASSERTE(mh_Edit==NULL); mh_Edit = NULL; mn_RebarHeight = nBarHeight; int nShiftY = SearchCtrlShift; //gpSetCls->EvalSize(SearchCtrlShift, esf_Vertical|esf_CanUseDpi); int nHeight = nBarHeight - (2 * nShiftY); int nWidth = nBarHeight * SearchCtrlWidthMul; mh_Pane = CreateWindowEx(WS_EX_CONTROLPARENT, FindPanelClass, L"", WS_CHILD|WS_VISIBLE, 0, nShiftY, nWidth, nHeight, hParent, NULL, NULL, this); return mh_Pane; }
// 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; }
/** * @function InitSearch */ void LJM2::InitSearch() { printf("Start Init Search \n"); //-- Reset the Hash Table for OpenSet and OpenSet mHT = new int[mNumNodes]; std::fill( mHT, mHT + mNumNodes, -1 ); ResetSearch(); printf("Finishing Init Search \n"); }
IPath::SearchResult CPathFinder::InitSearch(const MoveDef& moveDef, 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(moveDef, CMoveMath::BLOCK_STRUCTURE)) return IPath::CantGetCloser; // Clamp the start position if (startxSqr < 0) { startxSqr = 0; } if (startxSqr >= gs->mapx) { startxSqr = gs->mapxm1; } if (startzSqr < 0) { startzSqr = 0; } 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[startSquare] = (PATHOPT_START | PATHOPT_OPEN); squareStates.fCost[startSquare] = 0.0f; squareStates.gCost[startSquare] = 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(moveDef, pfDef, ownerId, synced); // if no improvements are found, then return CantGetCloser instead if ((goalSquare == startSquare && (!isStartGoal || pfDef.startInGoalRadius)) || goalSquare == 0) { return IPath::CantGetCloser; } return 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; }
IPathFinder::IPathFinder(unsigned int _BLOCK_SIZE) : BLOCK_SIZE(_BLOCK_SIZE) , BLOCK_PIXEL_SIZE(BLOCK_SIZE * SQUARE_SIZE) , nbrOfBlocks(mapDims.mapx / BLOCK_SIZE, mapDims.mapy / BLOCK_SIZE) , mStartBlockIdx(0) , mGoalBlockIdx(0) , mGoalHeuristic(0.0f) , maxBlocksToBeSearched(0) , testedBlocks(0) , instanceIndex(pathFinderInstances.size()) { pathFinderInstances.push_back(this); AllocStateBuffer(); ResetSearch(); }
// 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; }
/** * @function FindVarietyPaths2 * @brief Using Free Space */ std::vector< std::vector<Eigen::Vector3i> > LJM2::FindVarietyPaths2( int _x1, int _y1, int _z1, int _x2, int _y2, int _z2, int _times, float _alpha ) { mAlpha = _alpha; std::vector< std::vector<Eigen::Vector3i> > paths; std::vector<Eigen::Vector3i> path; std::vector< std::vector<int> > nodePaths; std::vector<int> allNodePaths; time_t ts; time_t tf; double dt; //-- Find the nearest points int startIndex = ref( _x1, _y1, _z1 ); int targetIndex = ref( _x2, _y2, _z2 ); printf("--> Start: %d Target: %d \n", startIndex, targetIndex ); InitSearch(); for( size_t i = 0; i < _times; ++i ) { path.resize(0); //ts = clock(); path = FindPath( startIndex, targetIndex ); //tf = clock(); printf("--[%d] Found Path of size %d \n", i, path.size() ); //printf(" Time elapsed: %.3f \n", (double) (tf - ts)/CLOCKS_PER_SEC ); paths.push_back( path ); nodePaths.push_back( mPath ); //-- Update the values //ts = clock(); ResetSearch(); //tf = clock(); //printf("--[%d] Search : Time elapsed: %.3f \n", i, (double) (tf - ts)/CLOCKS_PER_SEC ); allNodePaths = JoinPaths( nodePaths ); ts = clock(); UpdateNodeValues( allNodePaths ); //tf = clock(); //printf("--[%d] UpdateNodes : Time elapsed: %.3f \n", i, (double) (tf - ts)/CLOCKS_PER_SEC ); } return paths; }
/** * 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; }
void FolderListCtrl::OnTimer(UINT_PTR timer) { if (timer_ == timer) ResetSearch(); }
void FolderListCtrl::OnKeyDown(UINT chr, UINT rep_cnt, UINT flags) { switch (chr) { case VK_RETURN: ResetSearch(); { POSITION pos= GetFirstSelectedItemPosition(); int item= GetNextSelectedItem(pos); if (item >= 0) OpenItem(item); } return; case VK_BACK: ResetSearch(); GoLevelUp(); return; case VK_PRIOR: ResetSearch(); if (::GetKeyState(VK_CONTROL) < 0) { GoLevelUp(); return; } break; case VK_TAB: ResetSearch(); if (CWnd* wnd= GetParent()) { bool previous= ::GetKeyState(VK_SHIFT) < 0; wnd->SendMessage(WM_NEXTDLGCTL, previous ? 1 : 0, 0L); return; } break; case VK_ESCAPE: // propagate... ResetSearch(); if (CWnd* wnd= GetParent()) { wnd->SendMessage(WM_COMMAND, IDCANCEL, 0); return; } break; case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: case VK_NEXT: case VK_HOME: case VK_END: ResetSearch(); break; default: break; } Default(); }
/** * 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; }
CPathFinder::~CPathFinder() { ResetSearch(); squareStates.Clear(); }
CPathFinder::~CPathFinder() { ResetSearch(); }
/* 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; }
/* Destructor. Free used memory. */ CPathFinder::~CPathFinder() { ResetSearch(); delete[] squareState; }
// 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))]; }