Browse Source

More balanced treasure pile distribution.

DjWarmonger 11 years ago
parent
commit
3886a19771
3 changed files with 42 additions and 63 deletions
  1. 0 7
      lib/rmg/CRmgTemplateStorage.cpp
  2. 41 51
      lib/rmg/CRmgTemplateZone.cpp
  3. 1 5
      lib/rmg/CRmgTemplateZone.h

+ 0 - 7
lib/rmg/CRmgTemplateStorage.cpp

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

+ 41 - 51
lib/rmg/CRmgTemplateZone.cpp

@@ -138,8 +138,7 @@ CRmgTemplateZone::CRmgTemplateZone() :
 	matchTerrainToTown(true),
 	townType(ETownType::NEUTRAL),
 	terrainType (ETerrainType::GRASS),
-	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
-	totalDensity(0)
+	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL)
 {
 	terrainTypes = getDefaultTerrainTypes();
 }
@@ -303,16 +302,6 @@ void CRmgTemplateZone::setMonsterStrength (EMonsterStrength::EMonsterStrength va
 	zoneMonsterStrength = val;
 }
 
-void CRmgTemplateZone::setTotalDensity (ui16 val)
-{
-	totalDensity = val;
-}
-
-ui16 CRmgTemplateZone::getTotalDensity () const
-{
-	return totalDensity;
-}
-
 void CRmgTemplateZone::addTreasureInfo(CTreasureInfo & info)
 {
 	treasureInfo.push_back(info);
@@ -420,7 +409,11 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
 	std::set<int3> tilesToIgnore; //will be erased in this iteration
 
 	//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);
+
 	for (auto tile : tileinfo)
 	{
 		if (gen->isFree(tile))
@@ -686,7 +679,7 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength,
 	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;
 
@@ -695,25 +688,9 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float
 	int3 guardPos (-1,-1,-1);
 	info.nextTreasurePos = pos;
 
-	//default values
-	int maxValue = 5000;
-	int minValue = 1500;
-
-	if (treasureInfo.size())
-	{
-		//roulette wheel
-		int r = gen->rand.nextInt (1, totalDensity);
+	int maxValue = treasureInfo.max;
+	int minValue = treasureInfo.min;
 
-		for (auto t : treasureInfo)
-		{
-			if (r <= t.threshold)
-			{
-				maxValue = t.max;
-				minValue = t.min;
-				break;
-			}
-		}
-	}
 	ui32 desiredValue = gen->rand.nextInt(minValue, maxValue);
 	//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)
 {
-	//treasure density is proportional to map siz,e but must be scaled bakc to map size
-	//also, normalize it to zone count - higher count means relative smaller zones
+	auto valueComparator = [](const CTreasureInfo & lhs, const CTreasureInfo & rhs) -> bool
+	{
+		return lhs.max > rhs.max;
+	};
 
-	//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
+	//place biggest treasures first at large distance, place smaller ones inbetween
+	boost::sort(treasureInfo, valueComparator);
 
-	do {
-		
-		//optimization - don't check tiles which are not allowed
-		vstd::erase_if (possibleTiles, [gen](const int3 &tile) -> bool
-		{
-			return !gen->isPossible(tile);
-		});
+	int totalDensity = 0;
+	for (auto t : treasureInfo)
+	{
+		totalDensity += t.density;
 
-		int3 pos;
-		if ( ! findPlaceForTreasurePile(gen, minDistance, pos))		
-		{
-			break;
-		}
-		createTreasurePile (gen, pos, minDistance);
+		//treasure density is inversely proportional to zone size but must be scaled back to map size
+		//also, normalize it to zone count - higher count means relatively smaller zones
+
+		//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
 
-	} while(true);
+		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)

+ 1 - 5
lib/rmg/CRmgTemplateZone.h

@@ -63,7 +63,6 @@ public:
 	ui32 min;
 	ui32 max;
 	ui16 density;
-	ui16 threshold; //how much must RNG roll to pick that zone
 };
 
 struct DLL_LINKAGE ObjectInfo
@@ -152,7 +151,7 @@ public:
 
 	void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
 	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 placeMines (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);
 	std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
 
-	void setTotalDensity (ui16 val);
-	ui16 getTotalDensity () const;
 	void addConnection(TRmgTemplateZoneId otherZone);
 	std::vector<TRmgTemplateZoneId> getConnections() const;
 	void addTreasureInfo(CTreasureInfo & info);
@@ -196,7 +193,6 @@ private:
 	ETerrainType terrainType;
 
 	EMonsterStrength::EMonsterStrength zoneMonsterStrength;
-	ui16 totalDensity;
 	std::vector<CTreasureInfo> treasureInfo;
 	std::vector<ObjectInfo> possibleObjects;