1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Fix problems with water zone (#784)

This commit is contained in:
Nordsoft91 2022-08-28 12:54:06 +04:00 committed by Andrii Danylchenko
parent 4844310a89
commit ccbc8a1632
8 changed files with 25 additions and 13 deletions

View File

@ -85,8 +85,13 @@ bool Area::connected() const
return connected.empty(); return connected.empty();
} }
std::list<Area> connectedAreas(const Area & area) std::list<Area> connectedAreas(const Area & area, bool disableDiagonalConnections)
{ {
auto allDirs = int3::getDirs();
std::vector<int3> dirs(allDirs.begin(), allDirs.end());
if(disableDiagonalConnections)
dirs.assign(rmg::dirs4.begin(), rmg::dirs4.end());
std::list<Area> result; std::list<Area> result;
Tileset connected = area.getTiles(); Tileset connected = area.getTiles();
while(!connected.empty()) while(!connected.empty())
@ -101,7 +106,7 @@ std::list<Area> connectedAreas(const Area & area)
result.back().add(t); result.back().add(t);
queue.pop_front(); queue.pop_front();
for(auto & i : int3::getDirs()) for(auto & i : dirs)
{ {
auto tile = t + i; auto tile = t + i;
if(!queueSet.count(tile) && connected.count(tile) && !result.back().contains(tile)) if(!queueSet.count(tile) && connected.count(tile) && !result.back().contains(tile))

View File

@ -15,6 +15,9 @@
namespace rmg namespace rmg
{ {
static const std::array<int3, 4> dirs4 = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0) };
static const std::array<int3, 4> dirsDiagonal= { int3(1,1,0),int3(1,-1,0),int3(-1,1,0),int3(-1,-1,0) };
using Tileset = std::set<int3>; using Tileset = std::set<int3>;
using DistanceMap = std::map<int3, int>; using DistanceMap = std::map<int3, int>;
void toAbsolute(Tileset & tiles, const int3 & position); 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); //intersection
friend Area operator- (const Area & l, const Area & r); //AreaL reduced by tiles from AreaR 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 bool operator== (const Area & l, const Area & r);
friend std::list<Area> connectedAreas(const Area & area); friend std::list<Area> connectedAreas(const Area & area, bool disableDiagonalConnections);
private: private:

View File

@ -30,9 +30,6 @@
#include "Functions.h" #include "Functions.h"
#include "CMapGenerator.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) : RmgMap::RmgMap(const CMapGenOptions& mapGenOptions) :
mapGenOptions(mapGenOptions), zonesTotal(0) mapGenOptions(mapGenOptions), zonesTotal(0)
{ {
@ -54,7 +51,7 @@ void RmgMap::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> f
void RmgMap::foreachDirectNeighbour(const int3& pos, std::function<void(int3& pos)> foo) void RmgMap::foreachDirectNeighbour(const int3& pos, std::function<void(int3& pos)> foo)
{ {
for(const int3 &dir : dirs4) for(const int3 &dir : rmg::dirs4)
{ {
int3 n = pos + dir; int3 n = pos + dir;
if(mapInstance->isInTheMap(n)) if(mapInstance->isInTheMap(n))
@ -64,7 +61,7 @@ void RmgMap::foreachDirectNeighbour(const int3& pos, std::function<void(int3& po
void RmgMap::foreachDiagonalNeighbour(const int3& pos, std::function<void(int3& pos)> foo) void RmgMap::foreachDiagonalNeighbour(const int3& pos, std::function<void(int3& pos)> foo)
{ {
for (const int3 &dir : dirsDiagonal) for (const int3 &dir : rmg::dirsDiagonal)
{ {
int3 n = pos + dir; int3 n = pos + dir;
if (mapInstance->isInTheMap(n)) if (mapInstance->isInTheMap(n))

View File

@ -137,7 +137,7 @@ Path Path::search(const Tileset & dst, bool straight, std::function<float(const
auto dirs = int3::getDirs(); auto dirs = int3::getDirs();
std::vector<int3> neighbors(dirs.begin(), dirs.end()); std::vector<int3> neighbors(dirs.begin(), dirs.end());
if(straight) 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) for(auto & i : neighbors)
{ {
computeTileScore(currentNode + i); computeTileScore(currentNode + i);

View File

@ -715,7 +715,10 @@ void TreasurePlacer::createTreasures(ObjectManager & manager)
{ {
auto treasurePileInfos = prepareTreasurePile(t); auto treasurePileInfos = prepareTreasurePile(t);
if(treasurePileInfos.empty()) if(treasurePileInfos.empty())
break; {
++attempt;
continue;
}
int value = std::accumulate(treasurePileInfos.begin(), treasurePileInfos.end(), 0, [](int v, const ObjectInfo * oi){return v + oi->value;}); int value = std::accumulate(treasurePileInfos.begin(), treasurePileInfos.end(), 0, [](int v, const ObjectInfo * oi){return v + oi->value;});

View File

@ -93,7 +93,7 @@ const std::vector<WaterProxy::Lake> & WaterProxy::getLakes() const
void WaterProxy::collectLakes() void WaterProxy::collectLakes()
{ {
int lakeId = 0; int lakeId = 0;
for(auto lake : connectedAreas(zone.getArea())) for(auto lake : connectedAreas(zone.getArea(), true))
{ {
lakes.push_back(Lake{}); lakes.push_back(Lake{});
lakes.back().area = 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); bool guarded = manager->addGuard(rmgObject, guard);
auto waterAvailable = zone.areaPossible() + zone.freePaths(); auto waterAvailable = zone.areaPossible() + zone.freePaths();
waterAvailable.intersect(lake.area);
rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles
coast.intersect(land.areaPossible() + land.freePaths()); //having only available 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 auto boardingPositions = coast.getSubarea([&waterAvailable](const int3 & tile) //tiles where boarding is possible

View File

@ -34,6 +34,9 @@ void WaterRoutes::process()
if(!wproxy) if(!wproxy)
return; return;
if(auto * manager = zone.getModificator<ObjectManager>())
manager->createDistancesPriorityQueue();
for(auto & z : map.getZones()) for(auto & z : map.getZones())
{ {
if(z.first != zone.getId()) if(z.first != zone.getId())

View File

@ -159,7 +159,7 @@ rmg::Path Zone::searchPath(const rmg::Area & src, bool onlyStraight, std::functi
freePath.connect(dAreaFree); freePath.connect(dAreaFree);
//connect to all pieces //connect to all pieces
auto goals = connectedAreas(src); auto goals = connectedAreas(src, onlyStraight);
for(auto & goal : goals) for(auto & goal : goals)
{ {
auto path = freePath.search(goal, onlyStraight, movementCost); 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. //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) for(auto & area : areas)
{ {
if(dAreaFree.overlap(area)) if(dAreaFree.overlap(area))