void worldmap::Generate() { Alloc2D(OldAltitudeBuffer, XSize, YSize); Alloc2D(OldTypeBuffer, XSize, YSize); Alloc2D(NoIslandAltitudeBuffer, XSize, YSize); for(;;) { RandomizeAltitude(); SmoothAltitude(); GenerateClimate(); SmoothClimate(); CalculateContinents(); std::vector<continent*> PerfectForAttnam, PerfectForNewAttnam; for(uint c = 1; c < Continent.size(); ++c) if(Continent[c]->GetSize() > 250 && Continent[c]->GetSize() < 750 && Continent[c]->GetGTerrainAmount(EGForestType) && Continent[c]->GetGTerrainAmount(SnowType)) PerfectForAttnam.push_back(Continent[c]); if(!PerfectForAttnam.size()) continue; v2 AttnamPos, ElpuriCavePos, NewAttnamPos, TunnelEntry, TunnelExit; truth Correct = false; continent* PetrusLikes; // Store this before we start making islands which have no continent number. for(int x = 0; x < XSize; ++x) for(int y = 0; y < YSize; ++y) NoIslandAltitudeBuffer[x][y] = AltitudeBuffer[x][y]; for(int c1 = 0; c1 < 25; ++c1) { game::BusyAnimation(); PetrusLikes = PerfectForAttnam[RAND() % PerfectForAttnam.size()]; AttnamPos = PetrusLikes->GetRandomMember(EGForestType); ElpuriCavePos = PetrusLikes->GetRandomMember(SnowType); for(int c2 = 1; c2 < 50; ++c2) { TunnelExit = PetrusLikes->GetMember(RAND() % PetrusLikes->GetSize()); if(AttnamPos != TunnelExit && ElpuriCavePos != TunnelExit) { for(int d1 = 0; d1 < 8; ++d1) { v2 Pos = TunnelExit + game::GetMoveVector(d1); if(IsValidPos(Pos) && AltitudeBuffer[Pos.X][Pos.Y] <= 0) { int Distance = 3 + (RAND() & 3); truth Error = false; TunnelEntry = Pos; for(int c2 = 0; c2 < Distance; ++c2) { TunnelEntry += game::GetMoveVector(d1); if(!IsValidPos(TunnelEntry) || AltitudeBuffer[TunnelEntry.X][TunnelEntry.Y] > 0) { Error = true; break; } } if(Error) continue; int x, y; int Counter = 0; for(x = TunnelEntry.X - 3; x <= TunnelEntry.X + 3; ++x) { for(y = TunnelEntry.Y - 3; y <= TunnelEntry.Y + 3; ++y, ++Counter) if(Counter != 0 && Counter != 6 && Counter != 42 && Counter != 48 && (!IsValidPos(x, y) || AltitudeBuffer[x][y] > 0 || AltitudeBuffer[x][y] < -350)) { Error = true; break; } if(Error) break; } if(Error) continue; Error = true; for(x = 0; x < XSize; ++x) if(TypeBuffer[x][TunnelEntry.Y] == JungleType) { Error = false; break; } if(Error) continue; Counter = 0; for(x = TunnelEntry.X - 2; x <= TunnelEntry.X + 2; ++x) for(y = TunnelEntry.Y - 2; y <= TunnelEntry.Y + 2; ++y, ++Counter) if(Counter != 0 && Counter != 4 && Counter != 20 && Counter != 24) AltitudeBuffer[x][y] /= 2; AltitudeBuffer[TunnelEntry.X][TunnelEntry.Y] = 1 + RAND() % 50; TypeBuffer[TunnelEntry.X][TunnelEntry.Y] = JungleType; GetWSquare(TunnelEntry)->ChangeGWTerrain(jungle::Spawn()); int NewAttnamIndex; for(NewAttnamIndex = RAND() & 7; NewAttnamIndex == 7 - d1; NewAttnamIndex = RAND() & 7); NewAttnamPos = TunnelEntry + game::GetMoveVector(NewAttnamIndex); static int DiagonalDir[4] = { 0, 2, 5, 7 }; static int NotDiagonalDir[4] = { 1, 3, 4, 6 }; static int AdjacentDir[4][2] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 } }; truth Raised[] = { false, false, false, false }; int d2; for(d2 = 0; d2 < 4; ++d2) if(NotDiagonalDir[d2] != 7 - d1 && (NotDiagonalDir[d2] == NewAttnamIndex || !(RAND() & 2))) { v2 Pos = TunnelEntry + game::GetMoveVector(NotDiagonalDir[d2]); AltitudeBuffer[Pos.X][Pos.Y] = 1 + RAND() % 50; TypeBuffer[Pos.X][Pos.Y] = JungleType; GetWSquare(Pos)->ChangeGWTerrain(jungle::Spawn()); Raised[d2] = true; } for(d2 = 0; d2 < 4; ++d2) if(DiagonalDir[d2] != 7 - d1 && (DiagonalDir[d2] == NewAttnamIndex || (Raised[AdjacentDir[d2][0]] && Raised[AdjacentDir[d2][1]] && !(RAND() & 2)))) { v2 Pos = TunnelEntry + game::GetMoveVector(DiagonalDir[d2]); AltitudeBuffer[Pos.X][Pos.Y] = 1 + RAND() % 50; TypeBuffer[Pos.X][Pos.Y] = JungleType; GetWSquare(Pos)->ChangeGWTerrain(jungle::Spawn()); } Correct = true; break; } } if(Correct) break; } } if(Correct) break; } if(!Correct) continue; // Use a Poisson disc sampler to find random nicely-spaced points on the world map // Third argument is radius. Radius = 6 produces circa 120 positions (more spaced-out), Radius = 5 produces circa 200 positions (closer together) AllocateGlobalPossibleLocations(XSize, YSize, 6, 10); // Create a vector of location data structures from the available locations std::vector <location> AvailableLocations; // Pick out all the locations above ground as valid candidate locations for(int x1 = 0; x1 < XSize; ++x1) for(int y1 = 0; y1 < YSize; ++y1) if((PossibleLocationBuffer[x1][y1] == true) && (NoIslandAltitudeBuffer[x1][y1] > 0)) { AvailableLocations.push_back(location(v2(x1, y1), TypeBuffer[x1][y1], GetContinentUnder(v2(x1, y1))->GetIndex(), (AttnamPos - v2(x1, y1)).GetManhattanLength())); } // Remove those positions that have already been taken up by core places, plus the origin. Theoretically, New Attnam and Tunnel Entry need not be checked. std::vector<v2> ForbiddenPositions = {v2(0, 0), NewAttnamPos, TunnelEntry, TunnelExit, AttnamPos, ElpuriCavePos}; for(uint i = 0; i < ForbiddenPositions.size(); i++) { AvailableLocations.erase( std::remove_if( AvailableLocations.begin(), AvailableLocations.end(), [ForbiddenPositions, i](location vec) -> truth {return vec.Position == ForbiddenPositions[i];}), AvailableLocations.end()); } // Sort the vector of global available locations according to distance to attnam. Closest places are first. std::sort(AvailableLocations.begin(), AvailableLocations.end(), distancetoattnam()); // Make up a vector of places from the script that need to be placed std::vector<place> ToBePlaced; // Pick out only the places that can be generated, and get their native ground terrain type for(int Type = 1; Type < protocontainer<owterrain>::GetSize(); ++Type) { const owterrain::prototype* Proto = protocontainer<owterrain>::GetProto(Type); const owterrain::database*const* ConfigData = Proto->GetConfigData(); int ConfigSize = Proto->GetConfigSize(); for(int c = 0; c < ConfigSize; ++c) { const owterrain::database* DataBase = ConfigData[c]; if(!DataBase->IsAbstract && DataBase->CanBeGenerated) { place ConfigID(Type, DataBase->Config, DataBase->NativeGTerrainType, false, DataBase->CanBeOnAnyTerrain); ToBePlaced.push_back(ConfigID); } } } // Re-order the places so they appear in random order: std::random_shuffle(ToBePlaced.begin(), ToBePlaced.end()); // Do this for as many times as there are number of continents. for(uint c = 1; c < Continent.size(); ++c) { // Get the next nearest continent index by looking at the top of the available locations. int ThisContinent = AvailableLocations[0].ContinentIndex; // Get each available location on the first continent. std::vector<location> AvailableLocationsOnThisContinent; // Collect all remaining available locations on this continent. for(uint i = 0; i < AvailableLocations.size(); i++) { if(AvailableLocations[i].ContinentIndex == ThisContinent) { AvailableLocationsOnThisContinent.push_back(AvailableLocations[i]); } } // Go through all the locations on the continent. These are always in order of distance to Attnam, closest at the top. for(uint i = 0; i < AvailableLocationsOnThisContinent.size(); i++) { // Go through all remaining places. These are always in a random order :) for(uint j = 0; j < ToBePlaced.size(); j++) { // If the terrain type of the available location matches that of the place, then put the place there. if((AvailableLocationsOnThisContinent[i].GTerrainType == GetTypeOfNativeGTerrainType(ToBePlaced[j].NativeGTerrainType)) || (ToBePlaced[j].CanBeOnAnyTerrain)) { owterrain* NewPlace = protocontainer<owterrain>::GetProto(ToBePlaced[j].Type)->Spawn(); v2 NewPos = AvailableLocationsOnThisContinent[i].Position; if(!NewPlace->HideLocationInitially()) GetWSquare(NewPos)->ChangeOWTerrain(NewPlace); SetEntryPos(NewPlace->GetAttachedDungeon(), NewPos); ToBePlaced[j].HasBeenPlaced = true; if(NewPlace->RevealEnvironmentInitially()) RevealEnvironment(NewPos, 1); break; } } // Remove any places that have been placed, so we don't try to pick them out of our vector again. ToBePlaced.erase( std::remove_if( ToBePlaced.begin(), ToBePlaced.end(), [](place vec) -> truth {return vec.HasBeenPlaced;}), ToBePlaced.end()); } // Remove the locations on the continent we have just examined. Whether or not they populate with places, they will not be re-visited. AvailableLocations.erase( std::remove_if( AvailableLocations.begin(), AvailableLocations.end(), [ThisContinent](location vec) -> truth {return vec.ContinentIndex == ThisContinent;}), AvailableLocations.end()); AvailableLocationsOnThisContinent.clear(); // Two early stopping criteria. In the default case we just run out of continents to step through. if(AvailableLocations.empty()) break; if(ToBePlaced.empty()) break; } GetWSquare(AttnamPos)->ChangeOWTerrain(attnam::Spawn()); SetEntryPos(ATTNAM, AttnamPos); RevealEnvironment(AttnamPos, 1); GetWSquare(NewAttnamPos)->ChangeOWTerrain(newattnam::Spawn()); SetEntryPos(NEW_ATTNAM, NewAttnamPos); SetEntryPos(ELPURI_CAVE, ElpuriCavePos); GetWSquare(TunnelEntry)->ChangeOWTerrain(underwatertunnel::Spawn()); SetEntryPos(UNDER_WATER_TUNNEL, TunnelEntry); GetWSquare(TunnelExit)->ChangeOWTerrain(underwatertunnelexit::Spawn()); SetEntryPos(UNDER_WATER_TUNNEL_EXIT, TunnelExit); PLAYER->PutTo(NewAttnamPos); CalculateLuminances(); CalculateNeighbourBitmapPoses(); break; } delete [] OldAltitudeBuffer; delete [] OldTypeBuffer; delete [] NoIslandAltitudeBuffer; }
void worldmap::CalculateContinents() { uint c; for(c = 1; c < Continent.size(); ++c) delete Continent[c]; Continent.resize(1, 0); memset(ContinentBuffer[0], 0, XSizeTimesYSize * sizeof(uchar)); game::BusyAnimation(); for(int x = 0; x < XSize; ++x) for(int y = 0; y < YSize; ++y) if(AltitudeBuffer[x][y] > 0) { truth Attached = false; for(int d = 0; d < 8; ++d) { v2 Pos = v2(x, y) + game::GetMoveVector(d); if(IsValidPos(Pos)) { const int NearCont = ContinentBuffer[Pos.X][Pos.Y]; if(NearCont) { const int ThisCont = ContinentBuffer[x][y]; if(ThisCont) { if(ThisCont != NearCont) if(Continent[ThisCont]->GetSize() < Continent[NearCont]->GetSize()) Continent[ThisCont]->AttachTo(Continent[NearCont]); else Continent[NearCont]->AttachTo(Continent[ThisCont]); } else Continent[NearCont]->Add(v2(x, y)); Attached = true; } } } if(!Attached) { if(Continent.size() == 255) { RemoveEmptyContinents(); if(Continent.size() == 255) ABORT("Valpurus shall not carry more continents!"); } continent* NewContinent = new continent(Continent.size()); NewContinent->Add(v2(x, y)); Continent.push_back(NewContinent); } } RemoveEmptyContinents(); for(c = 1; c < Continent.size(); ++c) Continent[c]->GenerateInfo(); }
void worldmap::Generate() { Alloc2D(OldAltitudeBuffer, XSize, YSize); Alloc2D(OldTypeBuffer, XSize, YSize); for(;;) { RandomizeAltitude(); SmoothAltitude(); GenerateClimate(); SmoothClimate(); CalculateContinents(); std::vector<continent*> PerfectForAttnam, PerfectForNewAttnam; for(uint c = 1; c < Continent.size(); ++c) if(Continent[c]->GetSize() > 25 && Continent[c]->GetSize() < 1000 && Continent[c]->GetGTerrainAmount(EGForestType) && Continent[c]->GetGTerrainAmount(SnowType)) PerfectForAttnam.push_back(Continent[c]); if(!PerfectForAttnam.size()) continue; v2 AttnamPos, ElpuriCavePos, NewAttnamPos, TunnelEntry, TunnelExit; truth Correct = false; continent* PetrusLikes; for(int c1 = 0; c1 < 25; ++c1) { game::BusyAnimation(); PetrusLikes = PerfectForAttnam[RAND() % PerfectForAttnam.size()]; AttnamPos = PetrusLikes->GetRandomMember(EGForestType); ElpuriCavePos = PetrusLikes->GetRandomMember(SnowType); for(int c2 = 1; c2 < 50; ++c2) { TunnelExit = PetrusLikes->GetMember(RAND() % PetrusLikes->GetSize()); if(AttnamPos != TunnelExit && ElpuriCavePos != TunnelExit) { for(int d1 = 0; d1 < 8; ++d1) { v2 Pos = TunnelExit + game::GetMoveVector(d1); if(IsValidPos(Pos) && AltitudeBuffer[Pos.X][Pos.Y] <= 0) { int Distance = 3 + (RAND() & 3); truth Error = false; TunnelEntry = Pos; for(int c2 = 0; c2 < Distance; ++c2) { TunnelEntry += game::GetMoveVector(d1); if(!IsValidPos(TunnelEntry) || AltitudeBuffer[TunnelEntry.X][TunnelEntry.Y] > 0) { Error = true; break; } } if(Error) continue; int x, y; int Counter = 0; for(x = TunnelEntry.X - 3; x <= TunnelEntry.X + 3; ++x) { for(y = TunnelEntry.Y - 3; y <= TunnelEntry.Y + 3; ++y, ++Counter) if(Counter != 0 && Counter != 6 && Counter != 42 && Counter != 48 && (!IsValidPos(x, y) || AltitudeBuffer[x][y] > 0 || AltitudeBuffer[x][y] < -350)) { Error = true; break; } if(Error) break; } if(Error) continue; Error = true; for(x = 0; x < XSize; ++x) if(TypeBuffer[x][TunnelEntry.Y] == JungleType) { Error = false; break; } if(Error) continue; Counter = 0; for(x = TunnelEntry.X - 2; x <= TunnelEntry.X + 2; ++x) for(y = TunnelEntry.Y - 2; y <= TunnelEntry.Y + 2; ++y, ++Counter) if(Counter != 0 && Counter != 4 && Counter != 20 && Counter != 24) AltitudeBuffer[x][y] /= 2; AltitudeBuffer[TunnelEntry.X][TunnelEntry.Y] = 1 + RAND() % 50; TypeBuffer[TunnelEntry.X][TunnelEntry.Y] = JungleType; GetWSquare(TunnelEntry)->ChangeGWTerrain(jungle::Spawn()); int NewAttnamIndex; for(NewAttnamIndex = RAND() & 7; NewAttnamIndex == 7 - d1; NewAttnamIndex = RAND() & 7); NewAttnamPos = TunnelEntry + game::GetMoveVector(NewAttnamIndex); static int DiagonalDir[4] = { 0, 2, 5, 7 }; static int NotDiagonalDir[4] = { 1, 3, 4, 6 }; static int AdjacentDir[4][2] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 } }; truth Raised[] = { false, false, false, false }; int d2; for(d2 = 0; d2 < 4; ++d2) if(NotDiagonalDir[d2] != 7 - d1 && (NotDiagonalDir[d2] == NewAttnamIndex || !(RAND() & 2))) { v2 Pos = TunnelEntry + game::GetMoveVector(NotDiagonalDir[d2]); AltitudeBuffer[Pos.X][Pos.Y] = 1 + RAND() % 50; TypeBuffer[Pos.X][Pos.Y] = JungleType; GetWSquare(Pos)->ChangeGWTerrain(jungle::Spawn()); Raised[d2] = true; } for(d2 = 0; d2 < 4; ++d2) if(DiagonalDir[d2] != 7 - d1 && (DiagonalDir[d2] == NewAttnamIndex || (Raised[AdjacentDir[d2][0]] && Raised[AdjacentDir[d2][1]] && !(RAND() & 2)))) { v2 Pos = TunnelEntry + game::GetMoveVector(DiagonalDir[d2]); AltitudeBuffer[Pos.X][Pos.Y] = 1 + RAND() % 50; TypeBuffer[Pos.X][Pos.Y] = JungleType; GetWSquare(Pos)->ChangeGWTerrain(jungle::Spawn()); } Correct = true; break; } } if(Correct) break; } } if(Correct) break; } if(!Correct) continue; GetWSquare(AttnamPos)->ChangeOWTerrain(attnam::Spawn()); SetEntryPos(ATTNAM, AttnamPos); RevealEnvironment(AttnamPos, 1); GetWSquare(NewAttnamPos)->ChangeOWTerrain(newattnam::Spawn()); SetEntryPos(NEW_ATTNAM, NewAttnamPos); SetEntryPos(ELPURI_CAVE, ElpuriCavePos); GetWSquare(TunnelEntry)->ChangeOWTerrain(underwatertunnel::Spawn()); SetEntryPos(UNDER_WATER_TUNNEL, TunnelEntry); GetWSquare(TunnelExit)->ChangeOWTerrain(underwatertunnelexit::Spawn()); SetEntryPos(UNDER_WATER_TUNNEL_EXIT, TunnelExit); PLAYER->PutTo(NewAttnamPos); CalculateLuminances(); CalculateNeighbourBitmapPoses(); break; } delete [] OldAltitudeBuffer; delete [] OldTypeBuffer; }
//------------------------------------------------------ BOOL CRectTracker::TrackHandle( HWND hWnd, const LPPOINT point, int HitTest ) { ATLASSERT(point); if ((HitTest != hitBegin) && (HitTest != hitEnd) && (HitTest != hitMiddle)) return FALSE; if (!IsValidPos()) return FALSE; // set mouse cursor parameters RECT CursorRect; if (IsRectEmpty(&ValidRect)) { GetClientRect(hWnd, &CursorRect); } else { // valid rectangle is not empty if (HitTest == hitMiddle) { RECT BeginRect = ValidRect; OffsetRect(&BeginRect, point->x, point->y); OffsetRect(&BeginRect, -CurPos.Begin.x, -CurPos.Begin.y); NormalizeRect(&BeginRect); RECT EndRect = ValidRect; OffsetRect(&EndRect, point->x, point->y); OffsetRect(&EndRect, -CurPos.End.x, -CurPos.End.y); NormalizeRect(&EndRect); CursorRect = ValidRect; IntersectRect(&CursorRect, &CursorRect, &BeginRect); IntersectRect(&CursorRect, &CursorRect, &EndRect); } else CursorRect = ValidRect; }; if (IsRectEmpty(&CursorRect)) return FALSE; ClientToScreen(hWnd, (LPPOINT)&CursorRect ); ClientToScreen(hWnd, ((LPPOINT)&CursorRect)+1 ); ClipCursor(&CursorRect); SetCapture(hWnd); // get DC for drawing HDC dc = GetDC(hWnd); // set dc parameters HPEN LinePen = CreatePen( PS_SOLID, LineWidth, CLR_WHITE ); HPEN hOldPen = (HPEN)SelectObject(dc, LinePen); SetROP2(dc, R2_XORPEN ); KLinePos OriginalPos = CurPos; BOOL bCanceled = FALSE; // draw the rectangle for the first time DrawRect(dc, &CurPos.Begin, &CurPos.End); // get messages until capture lost or cancelled/accepted BOOL bExit = FALSE; KLinePos NewPos; while (!bExit) { MSG msg; BOOL b = ::GetMessage(&msg, NULL, 0, 0); ATLASSERT(b); if (GetCapture() != hWnd) break; // exit loop switch (msg.message) { // handle movement/accept messages case WM_LBUTTONUP: case WM_MOUSEMOVE: { NewPos = CurPos; POINT MousePoint = { (int)(short)LOWORD(msg.lParam), (int)(short)HIWORD(msg.lParam) }; switch (HitTest) { case hitBegin: NewPos.Begin = MousePoint; break; case hitEnd: NewPos.End = MousePoint; break; case hitMiddle: NewPos.Begin.x = OriginalPos.Begin.x + (MousePoint.x-point->x); NewPos.Begin.y = OriginalPos.Begin.y + (MousePoint.y-point->y); NewPos.End.x = OriginalPos.End.x + (MousePoint.x-point->x); NewPos.End.y = OriginalPos.End.y + (MousePoint.y-point->y); break; }; // redraw the line if ((NewPos.Begin.x != CurPos.Begin.x) || (NewPos.Begin.y != CurPos.Begin.y) || (NewPos.End.x != CurPos.End.x) || (NewPos.End.y != CurPos.End.y)) { // draw new rectangle DrawRect(dc, &NewPos.Begin, &NewPos.End); // erase old rectangle DrawRect(dc, &CurPos.Begin, &CurPos.End); }; if (IsValidPos(NewPos)) CurPos = NewPos; if (msg.message == WM_LBUTTONUP) bExit = TRUE; }; break; // handle cancel messages case WM_KEYDOWN: if (msg.wParam == VK_ESCAPE) { bCanceled = TRUE; bExit = TRUE; }; break; case WM_RBUTTONDOWN: bCanceled = TRUE; bExit = TRUE; break; // just dispatch rest of the messages default: DispatchMessage(&msg); break; } }; ClipCursor(NULL); ReleaseCapture(); if (bCanceled) CurPos = OriginalPos; SelectObject(dc, hOldPen); DeleteObject(LinePen); ReleaseDC(hWnd, dc); return !bCanceled; };
BYTE CPathFinder::CalculatePathTo(WORD x, WORD y, LPPATH lpBuffer, int nAdjust) { if (lpBuffer == NULL || x == 0 || y == 0 || !VerifyMemory()) return 0; memset(lpBuffer, 0, sizeof(PATH)); lpBuffer->posStart = GetPosition(); if (lpBuffer->posStart.x == 0 || lpBuffer->posStart.y == 0) return 0; if (!Search()) return 0; //GameInfof("Mapsize %d, %d", m_rightBottom.x - m_lefttTop.x, m_rightBottom.y - m_lefttTop.y); m_ptAbsDest.x = x; m_ptAbsDest.y = y; m_ptRelDest = m_ptAbsDest; MapToGraph(m_ptRelDest); //GameInfof("des %d, %d", m_ptRelDest.x, m_ptRelDest.y); // verify destination, see if it's in our map if (!IsValidPos(m_ptRelDest)) return 0; MakeMap2(); //DumpMap2(); POINT pos; pos.x = (short)lpBuffer->posStart.x; pos.y = (short)lpBuffer->posStart.y; lpBuffer->iNodeCount = 0; BOOL bOK = FALSE; int nRes = GetBestMove(pos, nAdjust); while (nRes != PATH_FAIL && lpBuffer->iNodeCount < 255) { // Reached? if (nRes == PATH_REACHED) { bOK = TRUE; lpBuffer->aPathNodes[lpBuffer->iNodeCount].x = x; lpBuffer->aPathNodes[lpBuffer->iNodeCount].y = y; lpBuffer->iNodeCount++; break; // Finished } // Perform a redundancy check int nRedundancy = GetRedundancy(lpBuffer, pos); if (nRedundancy == -1) { // no redundancy lpBuffer->aPathNodes[lpBuffer->iNodeCount].x = (WORD)pos.x; lpBuffer->aPathNodes[lpBuffer->iNodeCount].y = (WORD)pos.y; lpBuffer->iNodeCount++; } else { // redundancy found, discard all redundant steps lpBuffer->iNodeCount = nRedundancy + 1; lpBuffer->aPathNodes[lpBuffer->iNodeCount].x = (WORD)pos.x; lpBuffer->aPathNodes[lpBuffer->iNodeCount].y = (WORD)pos.y; } nRes = GetBestMove(pos, nAdjust); } if (!bOK) { lpBuffer->iNodeCount = 0; } else { lpBuffer->posEnd.x = x; lpBuffer->posEnd.y = y; } //DumpMap1(lpBuffer); // debug pictures return lpBuffer->iNodeCount; }
void CPathFinder::MakeMap2() { // convert the graph into a distance table for (int j = m_lefttTop.y; j < m_rightBottom.y; j++) { for (int i = m_lefttTop.x; i < m_rightBottom.x; i++) { if (m_graph[i][j]) m_graph[i][j] = static_cast<short>(GetDistance(i, j, m_ptRelDest.x, m_ptRelDest.y)); else m_graph[i][j] = RANGE_INVALID; } } //AdjustWalls(); if (IsValidPos(m_ptRelDest)) { //m_graph[m_ptRelDest.x][m_ptRelDest.y] = 1; m_graph[m_ptRelDest.x][m_ptRelDest.y] = 1; } /* // original Niren7's code, not working properly BOOL over=FALSE; int cur=1; while(!over) { over=TRUE; int i,j; for(i=0;i<DIM;i++) for(j=0;j<DIM;j++) { if(map[i][j] && m_disTable[i][j]==cur) { int x,y; for(x=i-1;x<=i+1;x++) for(y=j-1;y<=j+1;y++) { if(x<0||y<0||x>=DIM||y>=DIM) continue; if(!map[x][y]) continue; if(m_disTable[x][y]>0) continue; m_disTable[x][y]=cur+1; } over=FALSE; } } cur++; } for(i=0;i<DIM;i++) for(j=0;j<DIM;j++) { if(m_graph[i][j]==1) { int x,y; int d=5; for(x=i-5;x<=i+5;x++) for(y=j-5;y<=j+5;y++) { if(x<0||y<0||x>=DIM||y>=DIM) continue; if(m_graph[x][y]==0) { int d1=abs(x-i)+abs(y-j); if(d1<d)d=d1; } } m_disTable[i][j]+=5-d; } } //*/ }