1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Zone borders.

This commit is contained in:
DjWarmonger 2014-05-30 21:23:41 +02:00
parent 8c24ea0bfb
commit 8ab2a8df86
4 changed files with 78 additions and 46 deletions

View File

@ -14,11 +14,11 @@
#include "CRmgTemplateZone.h"
#include "CZonePlacer.h"
void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo)
void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo)
{
for(const int3 &dir : dirs)
{
const int3 n = pos + dir;
int3 n = pos + dir;
if(map->isInTheMap(n))
foo(pos+dir);
}
@ -227,6 +227,7 @@ void CMapGenerator::fillZones()
logGlobal->infoStream() << "Started filling zones";
for(auto it : zones)
{
it.second->createBorder(this);
it.second->fill(this);
}
logGlobal->infoStream() << "Zones filled successfully";
@ -249,28 +250,28 @@ std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
return zones;
}
bool CMapGenerator::isBlocked(int3 &tile) const
bool CMapGenerator::isBlocked(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isBlocked();
}
bool CMapGenerator::shouldBeBlocked(int3 &tile) const
bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
}
bool CMapGenerator::isPossible(int3 &tile) const
bool CMapGenerator::isPossible(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isPossible();
}
bool CMapGenerator::isFree(int3 &tile) const
bool CMapGenerator::isFree(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
@ -284,3 +285,27 @@ void CMapGenerator::setOccupied(int3 &tile, ETileType::ETileType state)
tiles[tile.x][tile.y][tile.z].setOccupied(state);
}
CTileInfo CMapGenerator::getTile(int3 tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z];
}
void CMapGenerator::setNearestObjectDistance(int3 &tile, int value)
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
}
int CMapGenerator::getNearestObjectDistance(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
}

View File

@ -64,13 +64,17 @@ public:
CMapEditManager * editManager;
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo);
void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
bool isBlocked(int3 &tile) const;
bool shouldBeBlocked(int3 &tile) const;
bool isPossible(int3 &tile) const;
bool isFree(int3 &tile) const;
bool isBlocked(const int3 &tile) const;
bool shouldBeBlocked(const int3 &tile) const;
bool isPossible(const int3 &tile) const;
bool isFree(const int3 &tile) const;
void setOccupied(int3 &tile, ETileType::ETileType state);
CTileInfo getTile(int3 tile) const;
int getNearestObjectDistance(const int3 &tile) const;
void setNearestObjectDistance(int3 &tile, int value);
private:
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;

View File

@ -313,7 +313,19 @@ void CRmgTemplateZone::setPos(const int3 &Pos)
void CRmgTemplateZone::addTile (const int3 &pos)
{
tileinfo[pos] = CTileInfo();
tileinfo.insert(pos);
}
void CRmgTemplateZone::createBorder(CMapGenerator* gen)
{
for (auto tile : tileinfo)
{
gen->foreach_neighbour (tile, [this, gen](int3 &pos)
{
if (!vstd::contains(this->tileinfo, pos))
gen->setOccupied (pos, ETileType::BLOCKED);
});
}
}
bool CRmgTemplateZone::fill(CMapGenerator* gen)
@ -385,7 +397,7 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
std::vector<int3> tiles;
for (auto tile : tileinfo)
{
tiles.push_back (tile.first);
tiles.push_back (tile);
}
gen->editManager->getTerrainSelection().setSelection(tiles);
gen->editManager->drawTerrain(VLC->townh->factions[townId]->nativeTerrain, &gen->rand);
@ -439,14 +451,14 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
auto sel = gen->editManager->getTerrainSelection();
sel.clearSelection();
for(auto it = tileinfo.begin(); it != tileinfo.end(); ++it)
for (auto tile : tileinfo)
{
if (it->second.shouldBeBlocked()) //fill tiles that should be blocked with obstacles
if (gen->shouldBeBlocked(tile)) //fill tiles that should be blocked with obstacles
{
auto obj = new CGObjectInstance();
obj->ID = static_cast<Obj>(130);
obj->subID = 0;
placeObject(gen, obj, it->first);
placeObject(gen, obj, tile);
}
}
//logGlobal->infoStream() << boost::format("Filling %d with ROCK") % sel.getSelectedItems().size();
@ -465,18 +477,18 @@ bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance*
auto ow = obj->getWidth();
auto oh = obj->getHeight();
//logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist;
for(auto it = tileinfo.begin(); it != tileinfo.end(); ++it)
for(auto tile : tileinfo)
{
auto &ti = it->second;
auto p = it->first;
auto &ti = gen->getTile(tile);
auto dist = ti.getNearestObjectDistance();
//avoid borders
if ((p.x < 3) || (w - p.x < 3) || (p.y < 3) || (h - p.y < 3))
if ((tile.x < 3) || (w - tile.x < 3) || (tile.y < 3) || (h - tile.y < 3))
continue;
if (!ti.isBlocked() && (dist >= min_dist) && (dist > best_distance))
if (gen->isPossible(tile) && (dist >= min_dist) && (dist > best_distance))
{
best_distance = dist;
pos = p;
pos = tile;
gen->setOccupied(pos, ETileType::BLOCKED);
result = true;
}
}
@ -519,15 +531,15 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
points.insert(pos);
for(auto const &p : points)
{
if (tileinfo.find(pos + p) != tileinfo.end())
if (vstd::contains(tileinfo, pos + p))
{
tileinfo[pos + p].setOccupied(ETileType::USED);
gen->setOccupied(pos + p, ETileType::USED);
}
}
for(auto it = tileinfo.begin(); it != tileinfo.end(); ++it)
for(auto tile : tileinfo)
{
si32 d = pos.dist2d(it->first);
it->second.setNearestObjectDistance(std::min(d, it->second.getNearestObjectDistance()));
si32 d = pos.dist2d(tile);
gen->setNearestObjectDistance(tile, std::min(d, gen->getNearestObjectDistance(tile)));
}
}
@ -537,32 +549,22 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
logGlobal->traceStream() << boost::format("Guard object at %d %d") % object->pos.x % object->pos.y;
int3 visitable = object->visitablePos();
std::vector<int3> tiles;
for(int i = -1; i < 2; ++i)
gen->foreach_neighbour(visitable, [&](int3& pos)
{
for(int j = -1; j < 2; ++j)
logGlobal->traceStream() << boost::format("Block at %d %d") % pos.x % pos.y;
if (gen->isPossible(pos))
{
auto it = tileinfo.find(visitable + int3(i, j, 0));
if (it != tileinfo.end())
{
if (it->first != visitable)
{
logGlobal->traceStream() << boost::format("Block at %d %d") % it->first.x % it->first.y;
if (it->second.isPossible())
{
tiles.push_back(it->first);
it->second.setOccupied(ETileType::BLOCKED);
}
}
}
}
}
tiles.push_back(pos);
gen->setOccupied(pos, ETileType::BLOCKED);
};
});
if ( ! tiles.size())
{
logGlobal->infoStream() << "Failed";
return false;
}
auto guard_tile = *RandomGeneratorUtil::nextItem(tiles, gen->rand);
tileinfo[guard_tile].setOccupied(ETileType::USED);
gen->setOccupied (guard_tile, ETileType::USED);
auto guard = new CGCreature();
guard->ID = Obj::RANDOM_MONSTER;
guard->subID = 0;

View File

@ -112,6 +112,7 @@ public:
void addTile (const int3 &pos);
void setShape(std::vector<int3> shape);
bool fill(CMapGenerator* gen);
void createBorder(CMapGenerator* gen);
void addConnection(TRmgTemplateZoneId otherZone);
std::vector<TRmgTemplateZoneId> getConnections() const;
@ -136,7 +137,7 @@ private:
//placement info
int3 pos;
float3 center;
std::map<int3, CTileInfo> tileinfo; //irregular area assined to zone
std::set<int3> tileinfo; //irregular area assined to zone
std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
std::map<TRmgTemplateZoneId, bool> alreadyConnected; //TODO: allow multiple connections between two zones?