소스 검색

More experiments WIP.

AlexVinS 10 년 전
부모
커밋
76193c4c5c
4개의 변경된 파일120개의 추가작업 그리고 47개의 파일을 삭제
  1. 38 21
      lib/rmg/CMapGenerator.cpp
  2. 5 0
      lib/rmg/CMapGenerator.h
  3. 67 22
      lib/rmg/CRmgTemplateZone.cpp
  4. 10 4
      lib/rmg/CRmgTemplateZone.h

+ 38 - 21
lib/rmg/CMapGenerator.cpp

@@ -433,8 +433,11 @@ void CMapGenerator::createConnections()
 					setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
 					setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
 					zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true);
 					zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true);
 					//zones can make paths only in their own area
 					//zones can make paths only in their own area
-					zoneA->crunchRoad(this, guardPos, posA, zoneA->getFreePaths()); //make connection towards our zone center
-					zoneB->crunchRoad(this, guardPos, posB, zoneB->getFreePaths()); //make connection towards other zone center
+					zoneA->crunchPath(this, guardPos, posA, zoneA->getFreePaths()); //make connection towards our zone center
+					zoneB->crunchPath(this, guardPos, posB, zoneB->getFreePaths()); //make connection towards other zone center		
+					
+					zoneA->addRoadNode(guardPos);
+					zoneB->addRoadNode(guardPos);
 					break; //we're done with this connection
 					break; //we're done with this connection
 				}
 				}
 			}
 			}
@@ -528,6 +531,13 @@ void CMapGenerator::addHeaderInfo()
 	addPlayerInfo();
 	addPlayerInfo();
 }
 }
 
 
+void CMapGenerator::checkIsOnMap(const int3& tile) const
+{
+	if (!map->isInTheMap(tile))
+		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));	
+}
+
+
 std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
 std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
 {
 {
 	return zones;
 	return zones;
@@ -535,67 +545,74 @@ std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
 
 
 bool CMapGenerator::isBlocked(const int3 &tile) const
 bool CMapGenerator::isBlocked(const int3 &tile) const
 {
 {
-	if (!map->isInTheMap(tile))
-		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z].isBlocked();
 	return tiles[tile.x][tile.y][tile.z].isBlocked();
 }
 }
 bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
 bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
 	return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
 }
 }
 bool CMapGenerator::isPossible(const int3 &tile) const
 bool CMapGenerator::isPossible(const int3 &tile) const
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z].isPossible();
 	return tiles[tile.x][tile.y][tile.z].isPossible();
 }
 }
 bool CMapGenerator::isFree(const int3 &tile) const
 bool CMapGenerator::isFree(const int3 &tile) const
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z].isFree();
 	return tiles[tile.x][tile.y][tile.z].isFree();
 }
 }
 bool CMapGenerator::isUsed(const int3 &tile) const
 bool CMapGenerator::isUsed(const int3 &tile) const
 {
 {
-	if (!map->isInTheMap(tile))
-		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z].isUsed();
 	return tiles[tile.x][tile.y][tile.z].isUsed();
 }
 }
+
+bool CMapGenerator::isRoad(const int3& tile) const
+{
+	checkIsOnMap(tile);
+	
+	return tiles[tile.x][tile.y][tile.z].isRoad();	
+}
+
 void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
 void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	tiles[tile.x][tile.y][tile.z].setOccupied(state);
 	tiles[tile.x][tile.y][tile.z].setOccupied(state);
 }
 }
 
 
-CTileInfo CMapGenerator::getTile(const int3&  tile) const
+void CMapGenerator::setRoad(const int3& tile, ERoadType::ERoadType roadType)
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
+
+	tiles[tile.x][tile.y][tile.z].setRoadType(roadType);	
+}
+
+
+CTileInfo CMapGenerator::getTile(const int3& tile) const
+{
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z];
 	return tiles[tile.x][tile.y][tile.z];
 }
 }
 
 
 void CMapGenerator::setNearestObjectDistance(int3 &tile, float value)
 void CMapGenerator::setNearestObjectDistance(int3 &tile, float value)
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
 	tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
 }
 }
 
 
 float CMapGenerator::getNearestObjectDistance(const int3 &tile) const
 float CMapGenerator::getNearestObjectDistance(const int3 &tile) const
 {
 {
-	if (!map->isInTheMap(tile))
-		throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+	checkIsOnMap(tile);
 
 
 	return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
 	return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
 }
 }

+ 5 - 0
lib/rmg/CMapGenerator.h

@@ -73,7 +73,11 @@ public:
 	bool isPossible(const int3 &tile) const;
 	bool isPossible(const int3 &tile) const;
 	bool isFree(const int3 &tile) const;
 	bool isFree(const int3 &tile) const;
 	bool isUsed(const int3 &tile) const;
 	bool isUsed(const int3 &tile) const;
+	bool isRoad(const int3 &tile) const;
+	
 	void setOccupied(const int3 &tile, ETileType::ETileType state);
 	void setOccupied(const int3 &tile, ETileType::ETileType state);
+	void setRoad(const int3 &tile, ERoadType::ERoadType roadType);
+	
 	CTileInfo getTile(const int3 & tile) const;
 	CTileInfo getTile(const int3 & tile) const;
 
 
 	float getNearestObjectDistance(const int3 &tile) const; 
 	float getNearestObjectDistance(const int3 &tile) const; 
@@ -100,6 +104,7 @@ private:
 	//int questArtsRemaining;
 	//int questArtsRemaining;
 	int monolithIndex;
 	int monolithIndex;
 	std::vector<ArtifactID> questArtifacts;
 	std::vector<ArtifactID> questArtifacts;
+	void checkIsOnMap(const int3 &tile) const; //throws
 
 
 	/// Generation methods
 	/// Generation methods
 	std::string getMapDescription() const;
 	std::string getMapDescription() const;

+ 67 - 22
lib/rmg/CRmgTemplateZone.cpp

@@ -33,6 +33,11 @@ CRmgTemplateZone::CTownInfo::CTownInfo() : townCount(0), castleCount(0), townDen
 
 
 }
 }
 
 
+void CRmgTemplateZone::addRoadNode(const int3& node)
+{
+	roadNodes.insert(node);
+}
+
 int CRmgTemplateZone::CTownInfo::getTownCount() const
 int CRmgTemplateZone::CTownInfo::getTownCount() const
 {
 {
 	return townCount;
 	return townCount;
@@ -111,6 +116,12 @@ bool CTileInfo::isFree() const
 {
 {
 	return occupied == ETileType::FREE;
 	return occupied == ETileType::FREE;
 }
 }
+
+bool CTileInfo::isRoad() const
+{
+	return roadType != ERoadType::NO_ROAD;
+}
+
 bool CTileInfo::isUsed() const
 bool CTileInfo::isUsed() const
 {
 {
 	return occupied == ETileType::USED;
 	return occupied == ETileType::USED;
@@ -692,6 +703,8 @@ bool CRmgTemplateZone::crunchRoad(CMapGenerator* gen, const int3& src, const int
 	if(crunchPath(gen, src, dst, &currentClearedTiles, true))
 	if(crunchPath(gen, src, dst, &currentClearedTiles, true))
 	{
 	{
 		roads.insert(std::begin(currentClearedTiles), std::end(currentClearedTiles));		
 		roads.insert(std::begin(currentClearedTiles), std::end(currentClearedTiles));		
+		roads.insert(src);
+		roads.insert(dst);
 		
 		
 		if(nullptr != clearedTiles)
 		if(nullptr != clearedTiles)
 			clearedTiles->insert(std::begin(currentClearedTiles), std::end(currentClearedTiles));
 			clearedTiles->insert(std::begin(currentClearedTiles), std::end(currentClearedTiles));
@@ -700,7 +713,8 @@ bool CRmgTemplateZone::crunchRoad(CMapGenerator* gen, const int3& src, const int
 	}
 	}
 	else
 	else
 	{
 	{
-		return false;
+		logGlobal->warnStream() << boost::format("Failed to crunch road from %s to %s") %src %dst;
+		return crunchPath(gen, src, dst, clearedTiles, false);
 	}
 	}
 }
 }
 
 
@@ -1265,6 +1279,7 @@ bool CRmgTemplateZone::placeMines (CMapGenerator* gen)
 bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
 bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
 {
 {
 	logGlobal->traceStream() << "Creating required objects";
 	logGlobal->traceStream() << "Creating required objects";
+	
 	for(const auto &obj : requiredObjects)
 	for(const auto &obj : requiredObjects)
 	{
 	{
 		int3 pos;
 		int3 pos;
@@ -1275,24 +1290,9 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
 			return false;
 			return false;
 		}		
 		}		
 	
 	
-		switch (obj.first->ID)
-		{
-		case Obj::TOWN:
-		case Obj::MONOLITH_TWO_WAY:
-		case Obj::SUBTERRANEAN_GATE:
-			{
-				crunchRoad(gen, this->pos, pos + obj.first->getVisitableOffset(), &freePaths);				
-			}
-			break;
-		
-		default:
-			break;
-		}
-		
-
 		placeObject (gen, obj.first, pos);
 		placeObject (gen, obj.first, pos);
 		guardObject (gen, obj.first, obj.second, (obj.first->ID == Obj::MONOLITH_TWO_WAY), true);
 		guardObject (gen, obj.first, obj.second, (obj.first->ID == Obj::MONOLITH_TWO_WAY), true);
-		//paths to required objects constitute main paths of zone. otherwise they just may lead to middle and create dead zones
+		//paths to required objects constitute main paths of zone. otherwise they just may lead to middle and create dead zones	
 	}
 	}
 
 
 	for (const auto &obj : closeObjects)
 	for (const auto &obj : closeObjects)
@@ -1481,18 +1481,45 @@ void CRmgTemplateZone::createObstacles2(CMapGenerator* gen)
 }
 }
 
 
 void CRmgTemplateZone::drawRoads(CMapGenerator* gen)
 void CRmgTemplateZone::drawRoads(CMapGenerator* gen)
+{
+	
+	auto doDrawRoad = []()
+	{
+		
+	};
+	
+	while(!roadNodes.empty())
+	{
+		int3 node = *roadNodes.begin(); 
+		roadNodes.erase(node);
+		if(roads.empty())
+		{
+			//start road network
+			roads.insert(node);
+		}
+		else
+		{
+			
+			int3 cross = *RandomGeneratorUtil::nextItem(roads, gen->rand);
+			
+			crunchRoad(gen, node, cross, &freePaths);						
+		}		
+	}
+}
+
+void CRmgTemplateZone::buildRoads(CMapGenerator* gen)
 {
 {
 	std::vector<int3> tiles;
 	std::vector<int3> tiles;
 	for (auto tile : roads)
 	for (auto tile : roads)
 	{
 	{
-		tiles.push_back (tile);
+		if(gen->map->isInTheMap(tile))	
+			tiles.push_back (tile);
 	}
 	}
 	gen->editManager->getTerrainSelection().setSelection(tiles);	
 	gen->editManager->getTerrainSelection().setSelection(tiles);	
-	gen->editManager->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand);
+	gen->editManager->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand);	
 }
 }
 
 
 
 
-
 bool CRmgTemplateZone::fill(CMapGenerator* gen)
 bool CRmgTemplateZone::fill(CMapGenerator* gen)
 {
 {
 	initTerrainType(gen);
 	initTerrainType(gen);
@@ -1503,11 +1530,11 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
 
 
 	placeMines(gen);
 	placeMines(gen);
 	createRequiredObjects(gen);
 	createRequiredObjects(gen);
+	drawRoads(gen); 
+	buildRoads(gen);
 	fractalize(gen); //after required objects are created and linked with their own paths
 	fractalize(gen); //after required objects are created and linked with their own paths
 	createTreasures(gen);
 	createTreasures(gen);
 	
 	
-	drawRoads(gen);
-	
 	logGlobal->infoStream() << boost::format ("Zone %d filled successfully") %id;
 	logGlobal->infoStream() << boost::format ("Zone %d filled successfully") %id;
 	return true;
 	return true;
 }
 }
@@ -1718,6 +1745,24 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
 		auto artid = sh->quest->m5arts.front();
 		auto artid = sh->quest->m5arts.front();
 		logGlobal->warnStream() << boost::format("Placed Seer Hut at %s, quest artifact %d is %s") % object->pos % artid % VLC->arth->artifacts[artid]->Name();
 		logGlobal->warnStream() << boost::format("Placed Seer Hut at %s, quest artifact %d is %s") % object->pos % artid % VLC->arth->artifacts[artid]->Name();
 	}
 	}
+
+	
+	switch (object->ID)
+	{
+	case Obj::TOWN:
+	case Obj::RANDOM_TOWN:
+	case Obj::MONOLITH_TWO_WAY:
+	case Obj::MONOLITH_ONE_WAY_ENTRANCE:
+	case Obj::MONOLITH_ONE_WAY_EXIT:
+	case Obj::SUBTERRANEAN_GATE:
+		{
+			roadNodes.insert(pos + object->getVisitableOffset());
+		}
+		break;
+	
+	default:
+		break;
+	}		
 }
 }
 
 
 void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard)
 void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard)

+ 10 - 4
lib/rmg/CRmgTemplateZone.h

@@ -47,10 +47,12 @@ public:
 	bool isPossible() const;
 	bool isPossible() const;
 	bool isFree() const;
 	bool isFree() const;
 	bool isUsed() const;
 	bool isUsed() const;
+	bool isRoad() const;	
 	void setOccupied(ETileType::ETileType value);
 	void setOccupied(ETileType::ETileType value);
 	ETerrainType getTerrainType() const;
 	ETerrainType getTerrainType() const;
 	ETileType::ETileType getTileType() const;
 	ETileType::ETileType getTileType() const;
 	void setTerrainType(ETerrainType value);
 	void setTerrainType(ETerrainType value);
+	
 	void setRoadType(ERoadType::ERoadType value);
 	void setRoadType(ERoadType::ERoadType value);
 private:
 private:
 	float nearestObjectDistance;
 	float nearestObjectDistance;
@@ -168,7 +170,7 @@ public:
 	void createObstacles1(CMapGenerator* gen);
 	void createObstacles1(CMapGenerator* gen);
 	void createObstacles2(CMapGenerator* gen);
 	void createObstacles2(CMapGenerator* gen);
 	bool crunchPath(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr, bool forRoad = false);
 	bool crunchPath(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr, bool forRoad = false);
-	bool crunchRoad(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr);
+	
 	std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
 	std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
 
 
 	void addConnection(TRmgTemplateZoneId otherZone);
 	void addConnection(TRmgTemplateZoneId otherZone);
@@ -181,7 +183,7 @@ public:
 	ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
 	ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
 
 
 	void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard = false);
 	void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard = false);
-
+	void addRoadNode(const int3 & node);
 private:
 private:
 	//template info
 	//template info
 	TRmgTemplateZoneId id;
 	TRmgTemplateZoneId id;
@@ -218,9 +220,11 @@ private:
 	std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
 	std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
 	std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
 	std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
 	
 	
-	std::set<int3> roads;
+	std::set<int3> roadNodes; //tiles to be connected with roads
+	std::set<int3> roads; //all tiles with roads
 	
 	
-	void drawRoads(CMapGenerator* gen);
+	void drawRoads(CMapGenerator* gen); //fills "roads" according to "roadNodes" 
+	void buildRoads(CMapGenerator* gen); //actually updates tiles
 
 
 	bool pointIsIn(int x, int y);
 	bool pointIsIn(int x, int y);
 	void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
 	void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
@@ -233,4 +237,6 @@ private:
 	void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
 	void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
 	void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance = true);
 	void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance = true);
 	bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false, bool addToFreePaths = false);
 	bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false, bool addToFreePaths = false);
+	//TODO:replace with A*-based algorithm on whole road network
+	bool crunchRoad(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr);
 };
 };