Kaynağa Gözat

Give every Zone its own RNG

Tomasz Zieliński 2 yıl önce
ebeveyn
işleme
15b254fded

+ 1 - 1
lib/rmg/CMapGenerator.cpp

@@ -127,7 +127,7 @@ std::unique_ptr<CMap> CMapGenerator::generate()
 	try
 	{
 		addHeaderInfo();
-		map->initTiles(*this);
+		map->initTiles(*this, rand);
 		Load::Progress::step();
 		initPrisonsRemaining();
 		initQuestArtsRemaining();

+ 1 - 2
lib/rmg/CMapGenerator.h

@@ -54,8 +54,6 @@ public:
 	
 	const Config & getConfig() const;
 	
-	CRandomGenerator rand;
-	
 	const CMapGenOptions& getMapGenOptions() const;
 	
 	std::unique_ptr<CMap> generate();
@@ -74,6 +72,7 @@ public:
 	int getRandomSeed() const;
 	
 private:
+	CRandomGenerator rand;
 	int randomSeed;
 	CMapGenOptions& mapGenOptions;
 	Config config;

+ 5 - 5
lib/rmg/RmgMap.cpp

@@ -77,7 +77,7 @@ void RmgMap::foreachDiagonalNeighbour(const int3 & pos, const std::function<void
 	}
 }
 
-void RmgMap::initTiles(CMapGenerator & generator)
+void RmgMap::initTiles(CMapGenerator & generator, CRandomGenerator & rand)
 {
 	mapInstance->initTerrain();
 	
@@ -88,15 +88,15 @@ void RmgMap::initTiles(CMapGenerator & generator)
 	for (auto faction : VLC->townh->getAllowedFactions())
 		zonesPerFaction[faction] = 0;
 	
-	getEditManager()->clearTerrain(&generator.rand);
+	getEditManager()->clearTerrain(&rand);
 	getEditManager()->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions.getWidth(), mapGenOptions.getHeight()));
-	getEditManager()->drawTerrain(ETerrainId::GRASS, &generator.rand);
+	getEditManager()->drawTerrain(ETerrainId::GRASS, &rand);
 
 	const auto * tmpl = mapGenOptions.getMapTemplate();
 	zones.clear();
 	for(const auto & option : tmpl->getZones())
 	{
-		auto zone = std::make_shared<Zone>(*this, generator);
+		auto zone = std::make_shared<Zone>(*this, generator, rand);
 		zone->setOptions(*option.second);
 		zones[zone->getId()] = zone;
 	}
@@ -109,7 +109,7 @@ void RmgMap::initTiles(CMapGenerator & generator)
 			rmg::ZoneOptions options;
 			options.setId(waterId);
 			options.setType(ETemplateZoneType::WATER);
-			auto zone = std::make_shared<Zone>(*this, generator);
+			auto zone = std::make_shared<Zone>(*this, generator, rand);
 			zone->setOptions(options);
 			zones[zone->getId()] = zone;
 			break;

+ 1 - 1
lib/rmg/RmgMap.h

@@ -75,7 +75,7 @@ public:
 	void registerZone(FactionID faction);
 	ui32 getZoneCount(FactionID faction);
 	ui32 getTotalZoneCount() const;
-	void initTiles(CMapGenerator & generator);
+	void initTiles(CMapGenerator & generator, CRandomGenerator & rand);
 	void addModificators();
 
 	bool isAllowedSpell(const SpellID & sid) const;

+ 8 - 3
lib/rmg/Zone.cpp

@@ -23,14 +23,14 @@ std::function<bool(const int3 &)> AREA_NO_FILTER = [](const int3 & t)
 	return true;
 };
 
-Zone::Zone(RmgMap & map, CMapGenerator & generator)
+Zone::Zone(RmgMap & map, CMapGenerator & generator, CRandomGenerator & r)
 	: finished(false)
 	, townType(ETownType::NEUTRAL)
 	, terrainType(ETerrainId::GRASS)
 	, map(map)
 	, generator(generator)
 {
-	
+	rand.setSeed(r.nextInt());
 }
 
 bool Zone::isUnderground() const
@@ -214,7 +214,7 @@ void Zone::fractalize()
 		{
 			//link tiles in random order
 			std::vector<int3> tilesToMakePath = possibleTiles.getTilesVector();
-			RandomGeneratorUtil::randomShuffle(tilesToMakePath, generator.rand);
+			RandomGeneratorUtil::randomShuffle(tilesToMakePath, getRand());
 			
 			int3 nodeFound(-1, -1, -1);
 
@@ -290,4 +290,9 @@ void Zone::initModificators()
 	logGlobal->info("Zone %d modificators initialized", getId());
 }
 
+CRandomGenerator& Zone::getRand()
+{
+	return rand;
+}
+
 VCMI_LIB_NAMESPACE_END

+ 5 - 2
lib/rmg/Zone.h

@@ -28,6 +28,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class RmgMap;
 class CMapGenerator;
 class Modificator;
+class CRandomGenerator;
 
 extern std::function<bool(const int3 &)> AREA_NO_FILTER;
 
@@ -36,7 +37,7 @@ typedef std::list<std::shared_ptr<Modificator>> TModificators;
 class Zone : public rmg::ZoneOptions
 {
 public:
-	Zone(RmgMap & map, CMapGenerator & generator);
+	Zone(RmgMap & map, CMapGenerator & generator, CRandomGenerator & rand);
 	Zone(const Zone &) = delete;
 	
 	void setOptions(const rmg::ZoneOptions & options);
@@ -84,13 +85,15 @@ public:
 	}
 	
 	void initModificators();
-
+	
+	CRandomGenerator & getRand();
 public:
 	boost::recursive_mutex areaMutex;
 	using Lock = boost::unique_lock<boost::recursive_mutex>;
 	
 protected:
 	CMapGenerator & generator;
+	CRandomGenerator rand;
 	RmgMap & map;
 	TModificators modificators;
 	bool finished;

+ 1 - 1
lib/rmg/modificators/ConnectionsPlacer.cpp

@@ -113,7 +113,7 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
 		int3 borderPos;
 		while(!directConnectionIterator->second.empty())
 		{
-			borderPos = *RandomGeneratorUtil::nextItem(directConnectionIterator->second, generator.rand);
+			borderPos = *RandomGeneratorUtil::nextItem(directConnectionIterator->second, zone.getRand());
 			guardPos = zone.areaPossible().nearest(borderPos);
 			assert(borderPos != guardPos);
 

+ 2 - 2
lib/rmg/modificators/MinePlacer.cpp

@@ -72,7 +72,7 @@ bool MinePlacer::placeMines(ObjectManager & manager)
 	}
 
 	//Shuffle mines to avoid patterns, but don't shuffle key objects like towns
-	RandomGeneratorUtil::randomShuffle(requiredObjects, generator.rand);
+	RandomGeneratorUtil::randomShuffle(requiredObjects, zone.getRand());
 	for (const auto& obj : requiredObjects)
 	{
 		manager.addRequiredObject(obj.first, obj.second);
@@ -83,7 +83,7 @@ bool MinePlacer::placeMines(ObjectManager & manager)
 	{
 		for(auto * mine : createdMines)
 		{
-			for(int rc = generator.rand.nextInt(1, extraRes); rc > 0; --rc)
+			for(int rc = zone.getRand().nextInt(1, extraRes); rc > 0; --rc)
 			{
 				auto * resourse = dynamic_cast<CGResource *>(VLC->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create());
 				resourse->amount = CGResource::RANDOM_AMOUNT;

+ 2 - 2
lib/rmg/modificators/ObjectDistributor.cpp

@@ -140,7 +140,7 @@ void ObjectDistributor::distributeSeerHuts()
 	const auto & zoneMap = map.getZones();
 	RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
 
-	RandomGeneratorUtil::randomShuffle(zones, generator.rand);
+	RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
 
 	const auto & possibleQuestArts = generator.getAllPossibleQuestArtifacts();
 	size_t availableArts = possibleQuestArts.size();
@@ -167,7 +167,7 @@ void ObjectDistributor::distributePrisons()
 	const auto & zoneMap = map.getZones();
 	RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
 
-	RandomGeneratorUtil::randomShuffle(zones, generator.rand);
+	RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
 
 	size_t allowedPrisons = generator.getPrisonsRemaning();
 	for (int i = zones.size() - 1; i >= 0; i--)

+ 4 - 4
lib/rmg/modificators/ObjectManager.cpp

@@ -294,7 +294,7 @@ bool ObjectManager::createRequiredObjects()
 				continue;
 			}
 			
-			rmgNearObject.setPosition(*RandomGeneratorUtil::nextItem(possibleArea.getTiles(), generator.rand));
+			rmgNearObject.setPosition(*RandomGeneratorUtil::nextItem(possibleArea.getTiles(), zone.getRand()));
 			placeObject(rmgNearObject, false, false);
 		}
 	}
@@ -342,7 +342,7 @@ bool ObjectManager::createRequiredObjects()
 				continue;
 			}
 			
-			rmgNearObject.setPosition(*RandomGeneratorUtil::nextItem(possibleArea.getTiles(), generator.rand));
+			rmgNearObject.setPosition(*RandomGeneratorUtil::nextItem(possibleArea.getTiles(), zone.getRand()));
 			placeObject(rmgNearObject, false, false);
 		}
 	}
@@ -482,10 +482,10 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
 	}
 	if(!possibleCreatures.empty())
 	{
-		creId = *RandomGeneratorUtil::nextItem(possibleCreatures, generator.rand);
+		creId = *RandomGeneratorUtil::nextItem(possibleCreatures, zone.getRand());
 		amount = strength / VLC->creh->objects[creId]->getAIValue();
 		if (amount >= 4)
-			amount = static_cast<int>(amount * generator.rand.nextDouble(0.75, 1.25));
+			amount = static_cast<int>(amount * zone.getRand().nextDouble(0.75, 1.25));
 	}
 	else //just pick any available creature
 	{

+ 1 - 1
lib/rmg/modificators/ObstaclePlacer.cpp

@@ -45,7 +45,7 @@ void ObstaclePlacer::process()
 	//TODO: Set prohibited area in ObstacleProxy :?
 	prohibitedArea = zone.freePaths() + zone.areaUsed() + manager->getVisitableArea();
 
-	auto objs = createObstacles(generator.rand);
+	auto objs = createObstacles(zone.getRand());
 	mapProxy->insertObjects(objs);
 }
 

+ 5 - 5
lib/rmg/modificators/QuestArtifactPlacer.cpp

@@ -23,7 +23,7 @@
 void QuestArtifactPlacer::process()
 {
 	findZonesForQuestArts();
-	placeQuestArtifacts(&generator.rand);
+	placeQuestArtifacts(zone.getRand());
 }
 
 void QuestArtifactPlacer::init()
@@ -71,11 +71,11 @@ void QuestArtifactPlacer::findZonesForQuestArts()
 	logGlobal->info("Number of nearby zones suitable for quest artifacts: %d", questArtZones.size());
 }
 
-void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator * rand)
+void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator & rand)
 {
 	for (const auto & artifactToPlace : questArtifactsToPlace)
 	{
-		RandomGeneratorUtil::randomShuffle(questArtZones, *rand);
+		RandomGeneratorUtil::randomShuffle(questArtZones, rand);
 		for (auto zone : questArtZones)
 		{
 			auto* qap = zone->getModificator<QuestArtifactPlacer>();
@@ -83,7 +83,7 @@ void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator * rand)
 			if (artifactsToReplace.empty())
 				continue;
 
-			auto artifactToReplace = *RandomGeneratorUtil::nextItem(artifactsToReplace, *rand);
+			auto artifactToReplace = *RandomGeneratorUtil::nextItem(artifactsToReplace, rand);
 			logGlobal->info("Replacing %s at %s with the quest artifact %s",
 				artifactToReplace->getObjectName(),
 				artifactToReplace->getPosition().toString(),
@@ -130,7 +130,7 @@ ArtifactID QuestArtifactPlacer::drawRandomArtifact()
 	{
 		ArtifactID ret = questArtifacts.back();
 		questArtifacts.pop_back();
-		RandomGeneratorUtil::randomShuffle(questArtifacts, generator.rand);
+		RandomGeneratorUtil::randomShuffle(questArtifacts, zone.getRand());
 		return ret;
 	}
 	else

+ 1 - 1
lib/rmg/modificators/QuestArtifactPlacer.h

@@ -31,7 +31,7 @@ public:
 	void addQuestArtifact(const ArtifactID& id);
 	void rememberPotentialArtifactToReplace(CGObjectInstance* obj);
 	std::vector<CGObjectInstance*> getPossibleArtifactsToReplace() const;
-	void placeQuestArtifacts(CRandomGenerator* rand);
+	void placeQuestArtifacts(CRandomGenerator & rand);
 	void dropReplacedArtifact(CGObjectInstance* obj);
 
 	size_t getMaxQuestArtifactCount() const;

+ 5 - 5
lib/rmg/modificators/RiverPlacer.cpp

@@ -88,7 +88,7 @@ void RiverPlacer::init()
 void RiverPlacer::drawRivers()
 {
 	auto tiles = rivers.getTilesVector();
-	mapProxy->drawRivers(generator.rand, tiles, zone.getTerrainType());
+	mapProxy->drawRivers(zone.getRand(), tiles, zone.getTerrainType());
 }
 
 char RiverPlacer::dump(const int3 & t)
@@ -137,7 +137,7 @@ void RiverPlacer::prepareHeightmap()
 
 	for(const auto & t : zone.area().getTilesVector())
 	{
-		heightMap[t] = generator.rand.nextInt(5);
+		heightMap[t] = zone.getRand().nextInt(5);
 		
 		if(roads.contains(t))
 			heightMap[t] += 30.f;
@@ -183,13 +183,13 @@ void RiverPlacer::preprocess()
 	//looking outside map
 	if(!outOfMapInternal.empty())
 	{
-		auto elem = *RandomGeneratorUtil::nextItem(outOfMapInternal.getTilesVector(), generator.rand);
+		auto elem = *RandomGeneratorUtil::nextItem(outOfMapInternal.getTilesVector(), zone.getRand());
 		source.add(elem);
 		outOfMapInternal.erase(elem);
 	}
 	if(!outOfMapInternal.empty())
 	{
-		auto elem = *RandomGeneratorUtil::nextItem(outOfMapInternal.getTilesVector(), generator.rand);
+		auto elem = *RandomGeneratorUtil::nextItem(outOfMapInternal.getTilesVector(), zone.getRand());
 		sink.add(elem);
 		outOfMapInternal.erase(elem);
 	}
@@ -294,7 +294,7 @@ void RiverPlacer::preprocess()
 	//decorative river
 	if(!sink.empty() && !source.empty() && riverNodes.empty() && !zone.areaPossible().empty())
 	{
-		addRiverNode(*RandomGeneratorUtil::nextItem(source.getTilesVector(), generator.rand));
+		addRiverNode(*RandomGeneratorUtil::nextItem(source.getTilesVector(), zone.getRand()));
 	}
 	
 	if(source.empty())

+ 1 - 1
lib/rmg/modificators/RoadPlacer.cpp

@@ -90,7 +90,7 @@ void RoadPlacer::drawRoads(bool secondary)
 
 	std::string roadName = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType);
 	RoadId roadType(*VLC->modh->identifiers.getIdentifier(CModHandler::scopeGame(), "road", roadName));
-	mapProxy->drawRoads(generator.rand, tiles, roadType);
+	mapProxy->drawRoads(zone.getRand(), tiles, roadType);
 }
 
 void RoadPlacer::addRoadNode(const int3& node)

+ 6 - 4
lib/rmg/modificators/RockFiller.cpp

@@ -53,20 +53,22 @@ void RockFiller::processMap()
 	//Merge all areas
 	for(auto & z : map.getZones())
 	{
-		if(auto * m = z.second->getModificator<RockPlacer>())
+		auto zone = z.second;
+		if(auto * m = zone->getModificator<RockPlacer>())
 		{
 			auto tiles = m->rockArea.getTilesVector();
-			mapProxy->drawTerrain(generator.rand, tiles, m->rockTerrain);
+			mapProxy->drawTerrain(zone->getRand(), tiles, m->rockTerrain);
 		}
 	}
 	
 	for(auto & z : map.getZones())
 	{
-		if(auto * m = z.second->getModificator<RockPlacer>())
+		auto zone = z.second;
+		if(auto * m = zone->getModificator<RockPlacer>())
 		{
 			//Now make sure all accessible tiles have no additional rock on them
 			auto tiles = m->accessibleArea.getTilesVector();
-			mapProxy->drawTerrain(generator.rand, tiles, z.second->getTerrainType());
+			mapProxy->drawTerrain(zone->getRand(), tiles, zone->getTerrainType());
 
 			m->postProcess();
 		}

+ 3 - 3
lib/rmg/modificators/TerrainPainter.cpp

@@ -28,7 +28,7 @@ void TerrainPainter::process()
 	initTerrainType();
 
 	auto v = zone.getArea().getTilesVector();
-	mapProxy->drawTerrain(generator.rand, v, zone.getTerrainType());
+	mapProxy->drawTerrain(zone.getRand(), v, zone.getTerrainType());
 }
 
 void TerrainPainter::init()
@@ -50,7 +50,7 @@ void TerrainPainter::initTerrainType()
 			if(terrain->isWater())
 				waterTerrains.push_back(terrain->getId());
 
-		zone.setTerrainType(*RandomGeneratorUtil::nextItem(waterTerrains, generator.rand));
+		zone.setTerrainType(*RandomGeneratorUtil::nextItem(waterTerrains, zone.getRand()));
 	}
 	else
 	{
@@ -78,7 +78,7 @@ void TerrainPainter::initTerrainType()
 			}
 			else
 			{
-				zone.setTerrainType(*RandomGeneratorUtil::nextItem(terrainTypes, generator.rand));
+				zone.setTerrainType(*RandomGeneratorUtil::nextItem(terrainTypes, zone.getRand()));
 			}
 		}
 

+ 6 - 6
lib/rmg/modificators/TownPlacer.cpp

@@ -119,16 +119,16 @@ void TownPlacer::placeTowns(ObjectManager & manager)
 	if(!totalTowns) //if there's no town present, get random faction for dwellings and pandoras
 	{
 		//25% chance for neutral
-		if (generator.rand.nextInt(1, 100) <= 25)
+		if (zone.getRand().nextInt(1, 100) <= 25)
 		{
 			zone.setTownType(ETownType::NEUTRAL);
 		}
 		else
 		{
 			if(!zone.getTownTypes().empty())
-				zone.setTownType(*RandomGeneratorUtil::nextItem(zone.getTownTypes(), generator.rand));
+				zone.setTownType(*RandomGeneratorUtil::nextItem(zone.getTownTypes(), zone.getRand()));
 			else if(!zone.getMonsterTypes().empty())
-				zone.setTownType(*RandomGeneratorUtil::nextItem(zone.getMonsterTypes(), generator.rand)); //this happens in Clash of Dragons in treasure zones, where all towns are banned
+				zone.setTownType(*RandomGeneratorUtil::nextItem(zone.getMonsterTypes(), zone.getRand())); //this happens in Clash of Dragons in treasure zones, where all towns are banned
 			else //just in any case
 				zone.setTownType(getRandomTownType());
 		}
@@ -182,9 +182,9 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player
 			if(!zone.areTownsSameType())
 			{
 				if(!zone.getTownTypes().empty())
-					subType = *RandomGeneratorUtil::nextItem(zone.getTownTypes(), generator.rand);
+					subType = *RandomGeneratorUtil::nextItem(zone.getTownTypes(), zone.getRand());
 				else
-					subType = *RandomGeneratorUtil::nextItem(zone.getDefaultTownTypes(), generator.rand); //it is possible to have zone with no towns allowed
+					subType = *RandomGeneratorUtil::nextItem(zone.getDefaultTownTypes(), zone.getRand()); //it is possible to have zone with no towns allowed
 			}
 		}
 		
@@ -235,7 +235,7 @@ si32 TownPlacer::getRandomTownType(bool matchUndergroundType)
 			townTypesAllowed = townTypesVerify;
 	}
 	
-	return *RandomGeneratorUtil::nextItem(townTypesAllowed, generator.rand);
+	return *RandomGeneratorUtil::nextItem(townTypesAllowed, zone.getRand());
 }
 
 int TownPlacer::getTotalTowns() const

+ 12 - 12
lib/rmg/modificators/TreasurePlacer.cpp

@@ -110,7 +110,7 @@ void TreasurePlacer::addAllPossibleObjects()
 		oi.generateObject = [i, this]() -> CGObjectInstance *
 		{
 			auto possibleHeroes = generator.getAllPossibleHeroes();
-			HeroTypeID hid = *RandomGeneratorUtil::nextItem(possibleHeroes, generator.rand);
+			HeroTypeID hid = *RandomGeneratorUtil::nextItem(possibleHeroes, zone.getRand());
 
 			auto factory = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0);
 			auto * obj = dynamic_cast<CGHeroInstance *>(factory->create());
@@ -208,7 +208,7 @@ void TreasurePlacer::addAllPossibleObjects()
 					out.push_back(spell->id);
 				}
 			}
-			auto * a = CArtifactInstance::createScroll(*RandomGeneratorUtil::nextItem(out, generator.rand));
+			auto * a = CArtifactInstance::createScroll(*RandomGeneratorUtil::nextItem(out, zone.getRand()));
 			obj->storedArtifact = a;
 			return obj;
 		};
@@ -322,7 +322,7 @@ void TreasurePlacer::addAllPossibleObjects()
 					spells.push_back(spell);
 			}
 			
-			RandomGeneratorUtil::randomShuffle(spells, generator.rand);
+			RandomGeneratorUtil::randomShuffle(spells, zone.getRand());
 			for(int j = 0; j < std::min(12, static_cast<int>(spells.size())); j++)
 			{
 				obj->spells.push_back(spells[j]->id);
@@ -351,7 +351,7 @@ void TreasurePlacer::addAllPossibleObjects()
 					spells.push_back(spell);
 			}
 			
-			RandomGeneratorUtil::randomShuffle(spells, generator.rand);
+			RandomGeneratorUtil::randomShuffle(spells, zone.getRand());
 			for(int j = 0; j < std::min(15, static_cast<int>(spells.size())); j++)
 			{
 				obj->spells.push_back(spells[j]->id);
@@ -379,7 +379,7 @@ void TreasurePlacer::addAllPossibleObjects()
 				spells.push_back(spell);
 		}
 		
-		RandomGeneratorUtil::randomShuffle(spells, generator.rand);
+		RandomGeneratorUtil::randomShuffle(spells, zone.getRand());
 		for(int j = 0; j < std::min(60, static_cast<int>(spells.size())); j++)
 		{
 			obj->spells.push_back(spells[j]->id);
@@ -411,7 +411,7 @@ void TreasurePlacer::addAllPossibleObjects()
 		//14 creatures per town + 4 for each of gold / exp reward
 		possibleSeerHuts.reserve(14 + 4 + 4);
 		
-		RandomGeneratorUtil::randomShuffle(creatures, generator.rand);
+		RandomGeneratorUtil::randomShuffle(creatures, zone.getRand());
 
 		for(int i = 0; i < static_cast<int>(creatures.size()); i++)
 		{
@@ -421,7 +421,7 @@ void TreasurePlacer::addAllPossibleObjects()
 			if(!creaturesAmount)
 				continue;
 			
-			int randomAppearance = chooseRandomAppearance(generator.rand, Obj::SEER_HUT, zone.getTerrainType());
+			int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType());
 			
 			oi.generateObject = [creature, creaturesAmount, randomAppearance, this, qap]() -> CGObjectInstance *
 			{
@@ -459,7 +459,7 @@ void TreasurePlacer::addAllPossibleObjects()
 		static int seerLevels = std::min(generator.getConfig().questValues.size(), generator.getConfig().questRewardValues.size());
 		for(int i = 0; i < seerLevels; i++) //seems that code for exp and gold reward is similiar
 		{
-			int randomAppearance = chooseRandomAppearance(generator.rand, Obj::SEER_HUT, zone.getTerrainType());
+			int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType());
 			
 			oi.setTemplate(Obj::SEER_HUT, randomAppearance, zone.getTerrainType());
 			oi.value = generator.getConfig().questValues[i];
@@ -519,7 +519,7 @@ void TreasurePlacer::addAllPossibleObjects()
 
 		for (size_t i = 0; i < questArtsRemaining; i++)
 		{
-			addObjectToRandomPool(*RandomGeneratorUtil::nextItem(possibleSeerHuts, generator.rand));
+			addObjectToRandomPool(*RandomGeneratorUtil::nextItem(possibleSeerHuts, zone.getRand()));
 		}
 	}
 }
@@ -553,7 +553,7 @@ std::vector<ObjectInfo*> TreasurePlacer::prepareTreasurePile(const CTreasureInfo
 	int maxValue = treasureInfo.max;
 	int minValue = treasureInfo.min;
 	
-	const ui32 desiredValue = generator.rand.nextInt(minValue, maxValue);
+	const ui32 desiredValue =zone.getRand().nextInt(minValue, maxValue);
 	
 	int currentValue = 0;
 	bool hasLargeObject = false;
@@ -631,7 +631,7 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
 				bestPositions = accessibleArea.getTilesVector();
 			}
 			
-			int3 nextPos = *RandomGeneratorUtil::nextItem(bestPositions, generator.rand);
+			int3 nextPos = *RandomGeneratorUtil::nextItem(bestPositions, zone.getRand());
 			instance.setPosition(nextPos - rmgObject.getPosition());
 			
 			auto instanceAccessibleArea = instance.getAccessibleArea();
@@ -686,7 +686,7 @@ ObjectInfo * TreasurePlacer::getRandomObject(ui32 desiredValue, ui32 currentValu
 	}
 	else
 	{
-		int r = generator.rand.nextInt(1, total);
+		int r = zone.getRand().nextInt(1, total);
 		auto sorter = [](const std::pair<ui32, ObjectInfo *> & rhs, const ui32 lhs) -> bool 
 		{
 			return static_cast<int>(rhs.first) < lhs; 

+ 3 - 3
lib/rmg/modificators/WaterAdopter.cpp

@@ -58,8 +58,8 @@ void WaterAdopter::createWater(EWaterContent::EWaterContent waterContent)
 	if(waterContent == EWaterContent::NORMAL)
 	{
 		waterArea.unite(collectDistantTiles(zone, zone.getSize() - 1));
-		auto sliceStart = RandomGeneratorUtil::nextItem(reverseDistanceMap[0], generator.rand);
-		auto sliceEnd = RandomGeneratorUtil::nextItem(reverseDistanceMap[0], generator.rand);
+		auto sliceStart = RandomGeneratorUtil::nextItem(reverseDistanceMap[0], zone.getRand());
+		auto sliceEnd = RandomGeneratorUtil::nextItem(reverseDistanceMap[0], zone.getRand());
 		
 		//at least 25% without water
 		bool endPassed = false;
@@ -97,7 +97,7 @@ void WaterAdopter::createWater(EWaterContent::EWaterContent waterContent)
 		const int coastLength = reverseDistanceMap[coastId].size() / (coastId + 3);
 		for(int coastIter = 0; coastIter < coastLength; ++coastIter)
 		{
-			int3 tile = *RandomGeneratorUtil::nextItem(reverseDistanceMap[coastId], generator.rand);
+			int3 tile = *RandomGeneratorUtil::nextItem(reverseDistanceMap[coastId], zone.getRand());
 			if(tilesChecked.find(tile) != tilesChecked.end())
 				continue;
 			

+ 3 - 3
lib/rmg/modificators/WaterProxy.cpp

@@ -39,7 +39,7 @@ void WaterProxy::process()
 	}
 	
 	auto v = zone.getArea().getTilesVector();
-	mapProxy->drawTerrain(generator.rand, v, zone.getTerrainType());
+	mapProxy->drawTerrain(zone.getRand(), v, zone.getTerrainType());
 	
 	//check terrain type
 	for([[maybe_unused]] const auto & t : zone.area().getTilesVector())
@@ -216,7 +216,7 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, RouteInfo & info)
 		return false;
 
 	auto subObjects = VLC->objtypeh->knownSubObjects(Obj::BOAT);
-	auto * boat = dynamic_cast<CGBoat *>(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(subObjects, generator.rand))->create());
+	auto * boat = dynamic_cast<CGBoat *>(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(subObjects, zone.getRand()))->create());
 
 	rmg::Object rmgObject(*boat);
 	rmgObject.setTemplate(zone.getTerrainType());
@@ -279,7 +279,7 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, Route
 	if(!manager)
 		return false;
 	
-	int subtype = chooseRandomAppearance(generator.rand, Obj::SHIPYARD, land.getTerrainType());
+	int subtype = chooseRandomAppearance(zone.getRand(), Obj::SHIPYARD, land.getTerrainType());
 	auto * shipyard = dynamic_cast<CGShipyard *>(VLC->objtypeh->getHandlerFor(Obj::SHIPYARD, subtype)->create());
 	shipyard->tempOwner = PlayerColor::NEUTRAL;