From ccbc8a163223878bea935f450baa70450a44f838 Mon Sep 17 00:00:00 2001 From: Nordsoft91 Date: Sun, 28 Aug 2022 12:54:06 +0400 Subject: [PATCH] Fix problems with water zone (#784) --- lib/rmg/RmgArea.cpp | 9 +++++++-- lib/rmg/RmgArea.h | 5 ++++- lib/rmg/RmgMap.cpp | 7 ++----- lib/rmg/RmgPath.cpp | 2 +- lib/rmg/TreasurePlacer.cpp | 5 ++++- lib/rmg/WaterProxy.cpp | 3 ++- lib/rmg/WaterRoutes.cpp | 3 +++ lib/rmg/Zone.cpp | 4 ++-- 8 files changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/rmg/RmgArea.cpp b/lib/rmg/RmgArea.cpp index 0c7d4fbf7..a2fb40045 100644 --- a/lib/rmg/RmgArea.cpp +++ b/lib/rmg/RmgArea.cpp @@ -85,8 +85,13 @@ bool Area::connected() const return connected.empty(); } -std::list connectedAreas(const Area & area) +std::list connectedAreas(const Area & area, bool disableDiagonalConnections) { + auto allDirs = int3::getDirs(); + std::vector dirs(allDirs.begin(), allDirs.end()); + if(disableDiagonalConnections) + dirs.assign(rmg::dirs4.begin(), rmg::dirs4.end()); + std::list result; Tileset connected = area.getTiles(); while(!connected.empty()) @@ -101,7 +106,7 @@ std::list connectedAreas(const Area & area) result.back().add(t); queue.pop_front(); - for(auto & i : int3::getDirs()) + for(auto & i : dirs) { auto tile = t + i; if(!queueSet.count(tile) && connected.count(tile) && !result.back().contains(tile)) diff --git a/lib/rmg/RmgArea.h b/lib/rmg/RmgArea.h index dcd03e691..bc821dc02 100644 --- a/lib/rmg/RmgArea.h +++ b/lib/rmg/RmgArea.h @@ -15,6 +15,9 @@ namespace rmg { + static const std::array dirs4 = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0) }; + static const std::array dirsDiagonal= { int3(1,1,0),int3(1,-1,0),int3(-1,1,0),int3(-1,-1,0) }; + using Tileset = std::set; using DistanceMap = std::map; void toAbsolute(Tileset & tiles, const int3 & position); @@ -66,7 +69,7 @@ namespace rmg friend Area operator* (const Area & l, const Area & r); //intersection friend Area operator- (const Area & l, const Area & r); //AreaL reduced by tiles from AreaR friend bool operator== (const Area & l, const Area & r); - friend std::list connectedAreas(const Area & area); + friend std::list connectedAreas(const Area & area, bool disableDiagonalConnections); private: diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index d6074106b..732bb59af 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -30,9 +30,6 @@ #include "Functions.h" #include "CMapGenerator.h" -static const int3 dirs4[] = {int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0)}; -static const int3 dirsDiagonal[] = { int3(1,1,0),int3(1,-1,0),int3(-1,1,0),int3(-1,-1,0) }; - RmgMap::RmgMap(const CMapGenOptions& mapGenOptions) : mapGenOptions(mapGenOptions), zonesTotal(0) { @@ -54,7 +51,7 @@ void RmgMap::foreach_neighbour(const int3 &pos, std::function f void RmgMap::foreachDirectNeighbour(const int3& pos, std::function foo) { - for(const int3 &dir : dirs4) + for(const int3 &dir : rmg::dirs4) { int3 n = pos + dir; if(mapInstance->isInTheMap(n)) @@ -64,7 +61,7 @@ void RmgMap::foreachDirectNeighbour(const int3& pos, std::function foo) { - for (const int3 &dir : dirsDiagonal) + for (const int3 &dir : rmg::dirsDiagonal) { int3 n = pos + dir; if (mapInstance->isInTheMap(n)) diff --git a/lib/rmg/RmgPath.cpp b/lib/rmg/RmgPath.cpp index 5fdd9a887..7e38ae04c 100644 --- a/lib/rmg/RmgPath.cpp +++ b/lib/rmg/RmgPath.cpp @@ -137,7 +137,7 @@ Path Path::search(const Tileset & dst, bool straight, std::function neighbors(dirs.begin(), dirs.end()); if(straight) - neighbors = { { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0) } }; + neighbors.assign(rmg::dirs4.begin(), rmg::dirs4.end()); for(auto & i : neighbors) { computeTileScore(currentNode + i); diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index 6cb161349..7e24f2d28 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -715,7 +715,10 @@ void TreasurePlacer::createTreasures(ObjectManager & manager) { auto treasurePileInfos = prepareTreasurePile(t); if(treasurePileInfos.empty()) - break; + { + ++attempt; + continue; + } int value = std::accumulate(treasurePileInfos.begin(), treasurePileInfos.end(), 0, [](int v, const ObjectInfo * oi){return v + oi->value;}); diff --git a/lib/rmg/WaterProxy.cpp b/lib/rmg/WaterProxy.cpp index 38ba3b6b4..5b5354c45 100644 --- a/lib/rmg/WaterProxy.cpp +++ b/lib/rmg/WaterProxy.cpp @@ -93,7 +93,7 @@ const std::vector & WaterProxy::getLakes() const void WaterProxy::collectLakes() { int lakeId = 0; - for(auto lake : connectedAreas(zone.getArea())) + for(auto lake : connectedAreas(zone.getArea(), true)) { lakes.push_back(Lake{}); lakes.back().area = lake; @@ -267,6 +267,7 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, Route bool guarded = manager->addGuard(rmgObject, guard); auto waterAvailable = zone.areaPossible() + zone.freePaths(); + waterAvailable.intersect(lake.area); rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles coast.intersect(land.areaPossible() + land.freePaths()); //having only available land tiles auto boardingPositions = coast.getSubarea([&waterAvailable](const int3 & tile) //tiles where boarding is possible diff --git a/lib/rmg/WaterRoutes.cpp b/lib/rmg/WaterRoutes.cpp index 1125c2c77..40569d4a2 100644 --- a/lib/rmg/WaterRoutes.cpp +++ b/lib/rmg/WaterRoutes.cpp @@ -34,6 +34,9 @@ void WaterRoutes::process() if(!wproxy) return; + if(auto * manager = zone.getModificator()) + manager->createDistancesPriorityQueue(); + for(auto & z : map.getZones()) { if(z.first != zone.getId()) diff --git a/lib/rmg/Zone.cpp b/lib/rmg/Zone.cpp index 627a397d1..d859cf449 100644 --- a/lib/rmg/Zone.cpp +++ b/lib/rmg/Zone.cpp @@ -159,7 +159,7 @@ rmg::Path Zone::searchPath(const rmg::Area & src, bool onlyStraight, std::functi freePath.connect(dAreaFree); //connect to all pieces - auto goals = connectedAreas(src); + auto goals = connectedAreas(src, onlyStraight); for(auto & goal : goals) { auto path = freePath.search(goal, onlyStraight, movementCost); @@ -235,7 +235,7 @@ void Zone::fractalize() } //cut straight paths towards the center. A* is too slow for that. - auto areas = connectedAreas(clearedTiles); + auto areas = connectedAreas(clearedTiles, false); for(auto & area : areas) { if(dAreaFree.overlap(area))