mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Huge optimization based on profiling - cut generation time by almost half (Jebus XL+U).
This commit is contained in:
@@ -60,6 +60,8 @@ void CMapGenerator::initTiles()
|
|||||||
tiles[i][j] = new CTileInfo[level];
|
tiles[i][j] = new CTileInfo[level];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zoneColouring.resize(boost::extents[map->twoLevel ? 2 : 1][map->width][map->height]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMapGenerator::~CMapGenerator()
|
CMapGenerator::~CMapGenerator()
|
||||||
@@ -697,6 +699,20 @@ CTileInfo CMapGenerator::getTile(const int3& tile) const
|
|||||||
return tiles[tile.x][tile.y][tile.z];
|
return tiles[tile.x][tile.y][tile.z];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRmgTemplateZoneId CMapGenerator::getZoneID(const int3& tile) const
|
||||||
|
{
|
||||||
|
checkIsOnMap(tile);
|
||||||
|
|
||||||
|
return zoneColouring[tile.z][tile.x][tile.y];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMapGenerator::setZoneID(const int3& tile, TRmgTemplateZoneId zid)
|
||||||
|
{
|
||||||
|
checkIsOnMap(tile);
|
||||||
|
|
||||||
|
zoneColouring[tile.z][tile.x][tile.y] = zid;
|
||||||
|
}
|
||||||
|
|
||||||
bool CMapGenerator::isAllowedSpell(SpellID sid) const
|
bool CMapGenerator::isAllowedSpell(SpellID sid) const
|
||||||
{
|
{
|
||||||
assert(sid >= 0);
|
assert(sid >= 0);
|
||||||
|
@@ -94,12 +94,16 @@ public:
|
|||||||
ui32 getZoneCount(TFaction faction);
|
ui32 getZoneCount(TFaction faction);
|
||||||
ui32 getTotalZoneCount() const;
|
ui32 getTotalZoneCount() const;
|
||||||
|
|
||||||
|
TRmgTemplateZoneId getZoneID(const int3& tile) const;
|
||||||
|
void setZoneID(const int3& tile, TRmgTemplateZoneId zid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
|
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
|
||||||
std::map<TFaction, ui32> zonesPerFaction;
|
std::map<TFaction, ui32> zonesPerFaction;
|
||||||
ui32 zonesTotal; //zones that have their main town only
|
ui32 zonesTotal; //zones that have their main town only
|
||||||
|
|
||||||
CTileInfo*** tiles;
|
CTileInfo*** tiles;
|
||||||
|
boost::multi_array<TRmgTemplateZoneId, 3> zoneColouring; //[z][x][y]
|
||||||
|
|
||||||
int prisonsRemaining;
|
int prisonsRemaining;
|
||||||
//int questArtsRemaining;
|
//int questArtsRemaining;
|
||||||
|
@@ -430,15 +430,21 @@ void CRmgTemplateZone::createBorder(CMapGenerator* gen)
|
|||||||
{
|
{
|
||||||
for (auto tile : tileinfo)
|
for (auto tile : tileinfo)
|
||||||
{
|
{
|
||||||
gen->foreach_neighbour (tile, [this, gen](int3 &pos)
|
bool edge = false;
|
||||||
|
gen->foreach_neighbour(tile, [this, gen, &edge](int3 &pos)
|
||||||
{
|
{
|
||||||
if (!vstd::contains(this->tileinfo, pos))
|
if (edge)
|
||||||
|
return; //optimization - do it only once
|
||||||
|
if (gen->getZoneID(pos) != id) //optimization - better than set search
|
||||||
{
|
{
|
||||||
gen->foreach_neighbour (pos, [this, gen](int3 &pos)
|
//we are edge if at least one tile does not belong to zone
|
||||||
|
//mark all nearby tiles blocked and we're done
|
||||||
|
gen->foreach_neighbour (pos, [this, gen](int3 &nearbyPos)
|
||||||
{
|
{
|
||||||
if (gen->isPossible(pos))
|
if (gen->isPossible(nearbyPos))
|
||||||
gen->setOccupied (pos, ETileType::BLOCKED);
|
gen->setOccupied(nearbyPos, ETileType::BLOCKED);
|
||||||
});
|
});
|
||||||
|
edge = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -663,7 +669,7 @@ do not leave zone border
|
|||||||
{
|
{
|
||||||
if (!gen->isBlocked(pos))
|
if (!gen->isBlocked(pos))
|
||||||
{
|
{
|
||||||
if (vstd::contains (tileinfo, pos))
|
if (gen->getZoneID(pos) == id)
|
||||||
{
|
{
|
||||||
if (gen->isPossible(pos))
|
if (gen->isPossible(pos))
|
||||||
{
|
{
|
||||||
@@ -700,7 +706,7 @@ do not leave zone border
|
|||||||
{
|
{
|
||||||
if (currentPos.dist2dSQ(dst) < lastDistance) //try closest tiles from all surrounding unused tiles
|
if (currentPos.dist2dSQ(dst) < lastDistance) //try closest tiles from all surrounding unused tiles
|
||||||
{
|
{
|
||||||
if (vstd::contains(tileinfo, pos))
|
if (gen->getZoneID(pos) == id)
|
||||||
{
|
{
|
||||||
if (gen->isPossible(pos))
|
if (gen->isPossible(pos))
|
||||||
{
|
{
|
||||||
@@ -799,7 +805,7 @@ bool CRmgTemplateZone::createRoad(CMapGenerator* gen, const int3& src, const int
|
|||||||
//if (gen->map->checkForVisitableDir(currentNode, &gen->map->getTile(pos), pos)) //TODO: why it has no effect?
|
//if (gen->map->checkForVisitableDir(currentNode, &gen->map->getTile(pos), pos)) //TODO: why it has no effect?
|
||||||
if (gen->isFree(pos) || pos == dst || (obj && obj->ID == Obj::MONSTER))
|
if (gen->isFree(pos) || pos == dst || (obj && obj->ID == Obj::MONSTER))
|
||||||
{
|
{
|
||||||
if (vstd::contains(this->tileinfo, pos) || pos == dst) //otherwise guard position may appear already connected to other zone.
|
if (gen->getZoneID(pos) == id || pos == dst) //otherwise guard position may appear already connected to other zone.
|
||||||
{
|
{
|
||||||
cameFrom[pos] = currentNode;
|
cameFrom[pos] = currentNode;
|
||||||
open.insert(pos);
|
open.insert(pos);
|
||||||
@@ -867,18 +873,19 @@ bool CRmgTemplateZone::connectPath(CMapGenerator* gen, const int3& src, bool onl
|
|||||||
{
|
{
|
||||||
auto foo = [gen, this, &open, &closed, &cameFrom, ¤tNode, &distances](int3& pos) -> void
|
auto foo = [gen, this, &open, &closed, &cameFrom, ¤tNode, &distances](int3& pos) -> void
|
||||||
{
|
{
|
||||||
|
if (gen->isBlocked(pos)) //no paths through blocked or occupied tiles
|
||||||
|
return;
|
||||||
|
|
||||||
int distance = distances[currentNode] + 1;
|
int distance = distances[currentNode] + 1;
|
||||||
int bestDistanceSoFar = 1e6; //FIXME: boost::limits
|
int bestDistanceSoFar = 1e6; //FIXME: boost::limits
|
||||||
auto it = distances.find(pos);
|
auto it = distances.find(pos);
|
||||||
if (it != distances.end())
|
if (it != distances.end())
|
||||||
bestDistanceSoFar = it->second;
|
bestDistanceSoFar = it->second;
|
||||||
|
|
||||||
if (gen->isBlocked(pos)) //no paths through blocked or occupied tiles
|
|
||||||
return;
|
|
||||||
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
||||||
{
|
{
|
||||||
//auto obj = gen->map->getTile(pos).topVisitableObj();
|
//auto obj = gen->map->getTile(pos).topVisitableObj();
|
||||||
if (vstd::contains(this->tileinfo, pos))
|
if (gen->getZoneID(pos) == id)
|
||||||
{
|
{
|
||||||
cameFrom[pos] = currentNode;
|
cameFrom[pos] = currentNode;
|
||||||
open.insert(pos);
|
open.insert(pos);
|
||||||
@@ -962,7 +969,7 @@ bool CRmgTemplateZone::connectWithCenter(CMapGenerator* gen, const int3& src, bo
|
|||||||
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
||||||
{
|
{
|
||||||
//auto obj = gen->map->getTile(pos).topVisitableObj();
|
//auto obj = gen->map->getTile(pos).topVisitableObj();
|
||||||
if (vstd::contains(this->tileinfo, pos))
|
if (gen->getZoneID(pos) == id)
|
||||||
{
|
{
|
||||||
cameFrom[pos] = currentNode;
|
cameFrom[pos] = currentNode;
|
||||||
open.insert(pos);
|
open.insert(pos);
|
||||||
@@ -1879,7 +1886,7 @@ void CRmgTemplateZone::drawRoads(CMapGenerator* gen)
|
|||||||
}
|
}
|
||||||
for (auto tile : roadNodes)
|
for (auto tile : roadNodes)
|
||||||
{
|
{
|
||||||
if (vstd::contains(tileinfo, tile)) //mark roads for our nodes, but not for zone guards in other zones
|
if (gen->getZoneID(tile) == id) //mark roads for our nodes, but not for zone guards in other zones
|
||||||
tiles.push_back(tile);
|
tiles.push_back(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -541,7 +541,9 @@ void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
|||||||
else
|
else
|
||||||
distances.push_back (std::make_pair(zone.second, std::numeric_limits<float>::max()));
|
distances.push_back (std::make_pair(zone.second, std::numeric_limits<float>::max()));
|
||||||
}
|
}
|
||||||
boost::min_element(distances, compareByDistance)->first->addTile(pos); //closest tile belongs to zone
|
auto zone = boost::min_element(distances, compareByDistance)->first; //closest tile belongs to zone
|
||||||
|
zone->addTile(pos);
|
||||||
|
gen->setZoneID(pos, zone->getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user