From 236b3ec8078b87d9c2fa42f75bad835df72b186a Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Thu, 12 Jun 2014 21:10:43 +0200 Subject: [PATCH] Zones will get random network of passable paths inside them. Treasures will try to fill all remaining fields. --- lib/rmg/CMapGenerator.cpp | 1 + lib/rmg/CRmgTemplateZone.cpp | 79 ++++++++++++++++++++++++++++++++++-- lib/rmg/CRmgTemplateZone.h | 4 +- 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index cf2c65636..f64e79e9e 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -219,6 +219,7 @@ void CMapGenerator::fillZones() { //make sure all connections are passable before creating borders it.second->createBorder(this); + it.second->fractalize(this); it.second->fill(this); } logGlobal->infoStream() << "Zones filled successfully"; diff --git a/lib/rmg/CRmgTemplateZone.cpp b/lib/rmg/CRmgTemplateZone.cpp index 02374dda5..9c98dd4c4 100644 --- a/lib/rmg/CRmgTemplateZone.cpp +++ b/lib/rmg/CRmgTemplateZone.cpp @@ -357,7 +357,78 @@ void CRmgTemplateZone::createBorder(CMapGenerator* gen) } } -bool CRmgTemplateZone::crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone) +void CRmgTemplateZone::fractalize(CMapGenerator* gen) +{ + std::vector clearedTiles; + std::set possibleTiles; + std::set tilesToClear; //will be set clear + std::set tilesToIgnore; //will be erased in this iteration + + const float minDistance = std::sqrt(totalDensity); + for (auto tile : tileinfo) + { + if (gen->isFree(tile)) + clearedTiles.push_back(tile); + else if (gen->isPossible(tile)); + possibleTiles.insert(tile); + } + if (clearedTiles.empty()) //this should come from zone connections + { + clearedTiles.push_back(pos); //zone center should be always clear + } + + while (possibleTiles.size()) + { + for (auto tileToMakePath : possibleTiles) + { + //find closest free tile + float currentDistance = 1e10; + int3 closestTile (-1,-1,-1); + + for (auto clearTile : clearedTiles) + { + float distance = tileToMakePath.dist2d(clearTile); + + if (distance < currentDistance) + { + currentDistance = distance; + closestTile = clearTile; + } + if (currentDistance <= minDistance) + { + //this tile is close enough. Forget about it and check next one + tilesToIgnore.insert (tileToMakePath); + break; + } + } + //if tiles is not close enough, make path to it + if (currentDistance > minDistance) + { + crunchPath (gen, tileToMakePath, closestTile, id, &tilesToClear); + break; //next iteration - use already cleared tiles + } + } + + for (auto tileToClear : tilesToClear) + { + //move cleared tiles from one set to another + clearedTiles.push_back(tileToClear); + vstd::erase_if_present(possibleTiles, tileToClear); + } + for (auto tileToClear : tilesToIgnore) + { + //these tiles are already connected, ignore them + vstd::erase_if_present(possibleTiles, tileToClear); + } + if (tilesToClear.empty()) //nothing else can be done (?) + break; + tilesToClear.clear(); //empty this container + tilesToIgnore.clear(); + } + logGlobal->infoStream() << boost::format ("Zone %d subdivided fractally") %id; +} + +bool CRmgTemplateZone::crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set* clearedTiles) { /* make shortest path with free tiles, reachning dst or closest already free tile. Avoid blocks. @@ -375,7 +446,7 @@ do not leave zone border break; auto lastDistance = distance; - gen->foreach_neighbour (currentPos, [this, gen, ¤tPos, dst, &distance, &result, &end](int3 &pos) + gen->foreach_neighbour (currentPos, [this, gen, ¤tPos, dst, &distance, &result, &end, clearedTiles](int3 &pos) { if (!result) //not sure if lambda is worth it... { @@ -393,6 +464,8 @@ do not leave zone border if (gen->isPossible(pos)) { gen->setOccupied (pos, ETileType::FREE); + if (clearedTiles) + clearedTiles->insert(pos); currentPos = pos; distance = currentPos.dist2dSQ (dst); } @@ -708,7 +781,7 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen) do { int3 pos; - if ( ! findPlaceForTreasurePile(gen, 5, pos)) + if ( ! findPlaceForTreasurePile(gen, 3, pos)) { break; } diff --git a/lib/rmg/CRmgTemplateZone.h b/lib/rmg/CRmgTemplateZone.h index eb05d0d97..aee6f1e38 100644 --- a/lib/rmg/CRmgTemplateZone.h +++ b/lib/rmg/CRmgTemplateZone.h @@ -133,7 +133,8 @@ public: bool createTreasurePile (CMapGenerator* gen, int3 &pos); bool fill(CMapGenerator* gen); void createBorder(CMapGenerator* gen); - bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone); + void fractalize(CMapGenerator* gen); + bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set* clearedTiles = nullptr); void setTotalDensity (ui16 val); ui16 getTotalDensity () const; @@ -162,7 +163,6 @@ private: std::vector possibleObjects; //content info - std::vector shape; //TODO: remove std::vector> requiredObjects; std::vector objects;