1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-23 21:29:13 +02:00

More balanced treasure pile distribution.

This commit is contained in:
DjWarmonger 2014-12-20 14:01:48 +01:00
parent 6fc873dcd5
commit 3886a19771
3 changed files with 42 additions and 63 deletions

View File

@ -133,7 +133,6 @@ void CJsonRmgTemplateLoader::loadTemplates()
//treasures //treasures
if (!zoneNode["treasure"].isNull()) if (!zoneNode["treasure"].isNull())
{ {
int totalDensity = 0;
//TODO: parse vector of different treasure settings //TODO: parse vector of different treasure settings
if (zoneNode["treasure"].getType() == JsonNode::DATA_STRUCT) if (zoneNode["treasure"].getType() == JsonNode::DATA_STRUCT)
{ {
@ -143,8 +142,6 @@ void CJsonRmgTemplateLoader::loadTemplates()
ti.min = treasureInfo["min"].Float(); ti.min = treasureInfo["min"].Float();
ti.max = treasureInfo["max"].Float(); ti.max = treasureInfo["max"].Float();
ti.density = treasureInfo["density"].Float(); //TODO: use me ti.density = treasureInfo["density"].Float(); //TODO: use me
totalDensity += ti.density;
ti.threshold = totalDensity;
zone->addTreasureInfo(ti); zone->addTreasureInfo(ti);
} }
} }
@ -156,12 +153,9 @@ void CJsonRmgTemplateLoader::loadTemplates()
ti.min = treasureInfo["min"].Float(); ti.min = treasureInfo["min"].Float();
ti.max = treasureInfo["max"].Float(); ti.max = treasureInfo["max"].Float();
ti.density = treasureInfo["density"].Float(); ti.density = treasureInfo["density"].Float();
totalDensity += ti.density;
ti.threshold = totalDensity;
zone->addTreasureInfo(ti); zone->addTreasureInfo(ti);
} }
} }
zone->setTotalDensity (totalDensity);
} }
zones[zone->getId()] = zone; zones[zone->getId()] = zone;
@ -191,7 +185,6 @@ void CJsonRmgTemplateLoader::loadTemplates()
{ {
zone->addTreasureInfo(treasureInfo); zone->addTreasureInfo(treasureInfo);
} }
zone->setTotalDensity (zones[zoneNode["treasureLikeZone"].Float()]->getTotalDensity());
} }
if (!zoneNode["minesLikeZone"].isNull()) if (!zoneNode["minesLikeZone"].isNull())

View File

@ -138,8 +138,7 @@ CRmgTemplateZone::CRmgTemplateZone() :
matchTerrainToTown(true), matchTerrainToTown(true),
townType(ETownType::NEUTRAL), townType(ETownType::NEUTRAL),
terrainType (ETerrainType::GRASS), terrainType (ETerrainType::GRASS),
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL), zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL)
totalDensity(0)
{ {
terrainTypes = getDefaultTerrainTypes(); terrainTypes = getDefaultTerrainTypes();
} }
@ -303,16 +302,6 @@ void CRmgTemplateZone::setMonsterStrength (EMonsterStrength::EMonsterStrength va
zoneMonsterStrength = val; zoneMonsterStrength = val;
} }
void CRmgTemplateZone::setTotalDensity (ui16 val)
{
totalDensity = val;
}
ui16 CRmgTemplateZone::getTotalDensity () const
{
return totalDensity;
}
void CRmgTemplateZone::addTreasureInfo(CTreasureInfo & info) void CRmgTemplateZone::addTreasureInfo(CTreasureInfo & info)
{ {
treasureInfo.push_back(info); treasureInfo.push_back(info);
@ -420,7 +409,11 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
std::set<int3> tilesToIgnore; //will be erased in this iteration std::set<int3> tilesToIgnore; //will be erased in this iteration
//the more treasure density, the greater distance between paths. Scaling is experimental. //the more treasure density, the greater distance between paths. Scaling is experimental.
int totalDensity = 0;
for (auto ti : treasureInfo)
totalDensity =+ ti.density;
const float minDistance = std::sqrt(totalDensity * 3); const float minDistance = std::sqrt(totalDensity * 3);
for (auto tile : tileinfo) for (auto tile : tileinfo)
{ {
if (gen->isFree(tile)) if (gen->isFree(tile))
@ -686,7 +679,7 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength,
return true; return true;
} }
bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float minDistance) bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance, const CTreasureInfo& treasureInfo)
{ {
CTreasurePileInfo info; CTreasurePileInfo info;
@ -695,25 +688,9 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float
int3 guardPos (-1,-1,-1); int3 guardPos (-1,-1,-1);
info.nextTreasurePos = pos; info.nextTreasurePos = pos;
//default values int maxValue = treasureInfo.max;
int maxValue = 5000; int minValue = treasureInfo.min;
int minValue = 1500;
if (treasureInfo.size())
{
//roulette wheel
int r = gen->rand.nextInt (1, totalDensity);
for (auto t : treasureInfo)
{
if (r <= t.threshold)
{
maxValue = t.max;
minValue = t.min;
break;
}
}
}
ui32 desiredValue = gen->rand.nextInt(minValue, maxValue); ui32 desiredValue = gen->rand.nextInt(minValue, maxValue);
//quantize value to let objects with value equal to max spawn too //quantize value to let objects with value equal to max spawn too
@ -1194,30 +1171,43 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
void CRmgTemplateZone::createTreasures(CMapGenerator* gen) void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
{ {
//treasure density is proportional to map siz,e but must be scaled bakc to map size auto valueComparator = [](const CTreasureInfo & lhs, const CTreasureInfo & rhs) -> bool
//also, normalize it to zone count - higher count means relative smaller zones {
return lhs.max > rhs.max;
};
//this is squared distance for optimization purposes //place biggest treasures first at large distance, place smaller ones inbetween
const double minDistance = std::max<float>((600.f * size * size * gen->getZones().size()) / boost::sort(treasureInfo, valueComparator);
(gen->mapGenOptions->getWidth() * gen->mapGenOptions->getHeight() * totalDensity * (gen->map->twoLevel ? 2 : 1)), 2);
//distance lower than 2 causes objects to overlap and crash
do { int totalDensity = 0;
for (auto t : treasureInfo)
//optimization - don't check tiles which are not allowed {
vstd::erase_if (possibleTiles, [gen](const int3 &tile) -> bool totalDensity += t.density;
{
return !gen->isPossible(tile);
});
int3 pos; //treasure density is inversely proportional to zone size but must be scaled back to map size
if ( ! findPlaceForTreasurePile(gen, minDistance, pos)) //also, normalize it to zone count - higher count means relatively smaller zones
{
break;
}
createTreasurePile (gen, pos, minDistance);
} while(true); //this is squared distance for optimization purposes
const double minDistance = std::max<float>((600.f * size * size * gen->getZones().size()) /
(gen->mapGenOptions->getWidth() * gen->mapGenOptions->getHeight() * totalDensity * (gen->map->twoLevel ? 2 : 1)), 2);
//distance lower than 2 causes objects to overlap and crash
do {
//optimization - don't check tiles which are not allowed
vstd::erase_if(possibleTiles, [gen](const int3 &tile) -> bool
{
return !gen->isPossible(tile);
});
int3 pos;
if (!findPlaceForTreasurePile(gen, minDistance, pos))
{
break;
}
createTreasurePile(gen, pos, minDistance, t);
} while (true);
}
} }
void CRmgTemplateZone::createObstacles(CMapGenerator* gen) void CRmgTemplateZone::createObstacles(CMapGenerator* gen)

View File

@ -63,7 +63,6 @@ public:
ui32 min; ui32 min;
ui32 max; ui32 max;
ui16 density; ui16 density;
ui16 threshold; //how much must RNG roll to pick that zone
}; };
struct DLL_LINKAGE ObjectInfo struct DLL_LINKAGE ObjectInfo
@ -152,7 +151,7 @@ public:
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0); void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false); bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
bool createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance); bool createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance, const CTreasureInfo& treasureInfo);
bool fill (CMapGenerator* gen); bool fill (CMapGenerator* gen);
bool placeMines (CMapGenerator* gen); bool placeMines (CMapGenerator* gen);
void initTownType (CMapGenerator* gen); void initTownType (CMapGenerator* gen);
@ -166,8 +165,6 @@ public:
bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set<int3>* clearedTiles = nullptr); bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set<int3>* clearedTiles = nullptr);
std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object); std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
void setTotalDensity (ui16 val);
ui16 getTotalDensity () const;
void addConnection(TRmgTemplateZoneId otherZone); void addConnection(TRmgTemplateZoneId otherZone);
std::vector<TRmgTemplateZoneId> getConnections() const; std::vector<TRmgTemplateZoneId> getConnections() const;
void addTreasureInfo(CTreasureInfo & info); void addTreasureInfo(CTreasureInfo & info);
@ -196,7 +193,6 @@ private:
ETerrainType terrainType; ETerrainType terrainType;
EMonsterStrength::EMonsterStrength zoneMonsterStrength; EMonsterStrength::EMonsterStrength zoneMonsterStrength;
ui16 totalDensity;
std::vector<CTreasureInfo> treasureInfo; std::vector<CTreasureInfo> treasureInfo;
std::vector<ObjectInfo> possibleObjects; std::vector<ObjectInfo> possibleObjects;