1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

multilevel support

This commit is contained in:
Laserlicht
2025-08-01 00:37:32 +02:00
parent 50a240a858
commit ecfe09f6b1
27 changed files with 156 additions and 107 deletions

View File

@@ -329,7 +329,7 @@ void CZonePlacer::placeZones(vstd::RNG * rand)
{
return pr.second->getType() == ETemplateZoneType::WATER;
});
bool underground = map.getMapGenOptions().getHasTwoLevels();
bool mapLevels = map.getMapGenOptions().getLevels();
findPathsBetweenZones();
placeOnGrid(rand);
@@ -347,7 +347,7 @@ void CZonePlacer::placeZones(vstd::RNG * rand)
RandomGeneratorUtil::randomShuffle(zonesVector, *rand);
//0. set zone sizes and surface / underground level
prepareZones(zones, zonesVector, underground, rand);
prepareZones(zones, zonesVector, mapLevels, rand);
std::map<std::shared_ptr<Zone>, float3> bestSolution;
@@ -441,21 +441,44 @@ void CZonePlacer::placeZones(vstd::RNG * rand)
}
}
void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const bool underground, vstd::RNG * rand)
void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const int mapLevels, vstd::RNG * rand)
{
std::vector<float> totalSize = { 0, 0 }; //make sure that sum of zone sizes on surface and uderground match size of the map
std::map<int, float> totalSize; //make sure that sum of zone sizes on surface and uderground match size of the map
int zonesOnLevel[2] = { 0, 0 };
std::map<int, int> zonesOnLevel;
for (int i = 0; i < mapLevels; i++)
zonesOnLevel[i] = 0;
//even distribution for surface / underground zones. Surface zones always have priority.
TZoneVector zonesToPlace;
std::map<TRmgTemplateZoneId, int> levels;
auto addZoneEqually = [&](auto & zone, bool ignoreUnderground = false) {
int chosenLevel = -1;
int minCount = std::numeric_limits<int>::max();
for (const auto& [level, count] : zonesOnLevel) {
if (ignoreUnderground && level == 1)
continue;
if (count < minCount ||
(count == minCount && level == 0) ||
(count == minCount && chosenLevel != 0 && level < chosenLevel))
{
chosenLevel = level;
minCount = count;
}
}
levels[zone.first] = chosenLevel;
zonesOnLevel[chosenLevel]++;
};
//first pass - determine fixed surface for zones
for(const auto & zone : zonesVector)
{
if (!underground) //this step is ignored
if (mapLevels == 1) //this step is ignored
zonesToPlace.push_back(zone);
else //place players depending on their factions
{
@@ -495,8 +518,7 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
else
{
//surface
zonesOnLevel[0]++;
levels[zone.first] = 0;
addZoneEqually(zone, true);
}
}
}
@@ -509,17 +531,8 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
}
for(const auto & zone : zonesToPlace)
{
if (underground) //only then consider underground zones
{
int level = 0;
if (zonesOnLevel[1] < zonesOnLevel[0]) //only if there are less underground zones
level = 1;
else
level = 0;
levels[zone.first] = level;
zonesOnLevel[level]++;
}
if (mapLevels > 1) //only then consider underground zones
addZoneEqually(zone);
else
levels[zone.first] = 0;
}
@@ -541,8 +554,8 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
prescaler = sqrt((WH)/(sum(n^2)*pi))
*/
std::vector<float> prescaler = { 0, 0 };
for (int i = 0; i < 2; i++)
std::map<int, float> prescaler;
for (int i = 0; i < mapLevels; i++)
prescaler[i] = std::sqrt((width * height) / (totalSize[i] * PI_CONSTANT));
mapSize = static_cast<float>(sqrt(width * height));
for(const auto & zone : zones)