瀏覽代碼

Zone borders.

DjWarmonger 11 年之前
父節點
當前提交
8ab2a8df86
共有 4 個文件被更改,包括 78 次插入46 次删除
  1. 31 6
      lib/rmg/CMapGenerator.cpp
  2. 9 5
      lib/rmg/CMapGenerator.h
  3. 36 34
      lib/rmg/CRmgTemplateZone.cpp
  4. 2 1
      lib/rmg/CRmgTemplateZone.h

+ 31 - 6
lib/rmg/CMapGenerator.cpp

@@ -14,11 +14,11 @@
 #include "CRmgTemplateZone.h"
 #include "CRmgTemplateZone.h"
 #include "CZonePlacer.h"
 #include "CZonePlacer.h"
 
 
-void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo)
+void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo)
 {
 {
 	for(const int3 &dir : dirs)
 	for(const int3 &dir : dirs)
 	{
 	{
-		const int3 n = pos + dir;
+		int3 n = pos + dir;
 		if(map->isInTheMap(n))
 		if(map->isInTheMap(n))
 			foo(pos+dir);
 			foo(pos+dir);
 	}
 	}
@@ -227,6 +227,7 @@ void CMapGenerator::fillZones()
 	logGlobal->infoStream() << "Started filling zones";
 	logGlobal->infoStream() << "Started filling zones";
 	for(auto it : zones)
 	for(auto it : zones)
 	{
 	{
+		it.second->createBorder(this);
 		it.second->fill(this);
 		it.second->fill(this);
 	}	
 	}	
 	logGlobal->infoStream() << "Zones filled successfully";
 	logGlobal->infoStream() << "Zones filled successfully";
@@ -249,28 +250,28 @@ std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
 	return zones;
 	return zones;
 }
 }
 
 
-bool CMapGenerator::isBlocked(int3 &tile) const
+bool CMapGenerator::isBlocked(const int3 &tile) const
 {
 {
 	if (!map->isInTheMap(tile))
 	if (!map->isInTheMap(tile))
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 
 
 	return tiles[tile.x][tile.y][tile.z].isBlocked();
 	return tiles[tile.x][tile.y][tile.z].isBlocked();
 }
 }
-bool CMapGenerator::shouldBeBlocked(int3 &tile) const
+bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
 {
 {
 	if (!map->isInTheMap(tile))
 	if (!map->isInTheMap(tile))
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 
 
 	return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
 	return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
 }
 }
-bool CMapGenerator::isPossible(int3 &tile) const
+bool CMapGenerator::isPossible(const int3 &tile) const
 {
 {
 	if (!map->isInTheMap(tile))
 	if (!map->isInTheMap(tile))
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 
 
 	return tiles[tile.x][tile.y][tile.z].isPossible();
 	return tiles[tile.x][tile.y][tile.z].isPossible();
 }
 }
-bool CMapGenerator::isFree(int3 &tile) const
+bool CMapGenerator::isFree(const int3 &tile) const
 {
 {
 	if (!map->isInTheMap(tile))
 	if (!map->isInTheMap(tile))
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
 		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
@@ -284,3 +285,27 @@ void CMapGenerator::setOccupied(int3 &tile, ETileType::ETileType state)
 
 
 	tiles[tile.x][tile.y][tile.z].setOccupied(state);
 	tiles[tile.x][tile.y][tile.z].setOccupied(state);
 }
 }
+
+CTileInfo CMapGenerator::getTile(int3 tile) const
+{
+	if (!map->isInTheMap(tile))
+		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+
+	return tiles[tile.x][tile.y][tile.z];
+}
+
+void CMapGenerator::setNearestObjectDistance(int3 &tile, int value)
+{
+	if (!map->isInTheMap(tile))
+		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+
+	tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
+}
+
+int CMapGenerator::getNearestObjectDistance(const int3 &tile) const
+{
+	if (!map->isInTheMap(tile))
+		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+
+	return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
+}

+ 9 - 5
lib/rmg/CMapGenerator.h

@@ -64,13 +64,17 @@ public:
 	CMapEditManager * editManager;
 	CMapEditManager * editManager;
 
 
 	std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
 	std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
-	void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo);
+	void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
 
 
-	bool isBlocked(int3 &tile) const;
-	bool shouldBeBlocked(int3 &tile) const;
-	bool isPossible(int3 &tile) const;
-	bool isFree(int3 &tile) const;
+	bool isBlocked(const int3 &tile) const;
+	bool shouldBeBlocked(const int3 &tile) const;
+	bool isPossible(const int3 &tile) const;
+	bool isFree(const int3 &tile) const;
 	void setOccupied(int3 &tile, ETileType::ETileType state);
 	void setOccupied(int3 &tile, ETileType::ETileType state);
+	CTileInfo getTile(int3 tile) const;
+
+	int getNearestObjectDistance(const int3 &tile) const; 
+	void setNearestObjectDistance(int3 &tile, int value); 
 
 
 private:
 private:
 	std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
 	std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;

+ 36 - 34
lib/rmg/CRmgTemplateZone.cpp

@@ -313,7 +313,19 @@ void CRmgTemplateZone::setPos(const int3 &Pos)
 
 
 void CRmgTemplateZone::addTile (const int3 &pos)
 void CRmgTemplateZone::addTile (const int3 &pos)
 {
 {
-	tileinfo[pos] = CTileInfo();
+	tileinfo.insert(pos);
+}
+
+void CRmgTemplateZone::createBorder(CMapGenerator* gen)
+{
+	for (auto tile : tileinfo)
+	{
+		gen->foreach_neighbour (tile, [this, gen](int3 &pos)
+		{
+			if (!vstd::contains(this->tileinfo, pos))
+				gen->setOccupied (pos, ETileType::BLOCKED);
+		});
+	}
 }
 }
 
 
 bool CRmgTemplateZone::fill(CMapGenerator* gen)
 bool CRmgTemplateZone::fill(CMapGenerator* gen)
@@ -385,7 +397,7 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
 	std::vector<int3> tiles;
 	std::vector<int3> tiles;
 	for (auto tile : tileinfo)
 	for (auto tile : tileinfo)
 	{
 	{
-		tiles.push_back (tile.first);
+		tiles.push_back (tile);
 	}
 	}
 	gen->editManager->getTerrainSelection().setSelection(tiles);
 	gen->editManager->getTerrainSelection().setSelection(tiles);
 	gen->editManager->drawTerrain(VLC->townh->factions[townId]->nativeTerrain, &gen->rand);
 	gen->editManager->drawTerrain(VLC->townh->factions[townId]->nativeTerrain, &gen->rand);
@@ -439,14 +451,14 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
 
 
 	auto sel = gen->editManager->getTerrainSelection();
 	auto sel = gen->editManager->getTerrainSelection();
 	sel.clearSelection();
 	sel.clearSelection();
-	for(auto it = tileinfo.begin(); it != tileinfo.end(); ++it)
+	for (auto tile : tileinfo)
 	{
 	{
-		if (it->second.shouldBeBlocked()) //fill tiles that should be blocked with obstacles
+		if (gen->shouldBeBlocked(tile)) //fill tiles that should be blocked with obstacles
 		{
 		{
 			auto obj = new CGObjectInstance();
 			auto obj = new CGObjectInstance();
 			obj->ID = static_cast<Obj>(130);
 			obj->ID = static_cast<Obj>(130);
 			obj->subID = 0;
 			obj->subID = 0;
-			placeObject(gen, obj, it->first);
+			placeObject(gen, obj, tile);
 		}
 		}
 	}
 	}
 	//logGlobal->infoStream() << boost::format("Filling %d with ROCK") % sel.getSelectedItems().size();
 	//logGlobal->infoStream() << boost::format("Filling %d with ROCK") % sel.getSelectedItems().size();
@@ -465,18 +477,18 @@ bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance*
 	auto ow = obj->getWidth();
 	auto ow = obj->getWidth();
 	auto oh = obj->getHeight();
 	auto oh = obj->getHeight();
 	//logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist;
 	//logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist;
-	for(auto it = tileinfo.begin(); it != tileinfo.end(); ++it)
+	for(auto tile : tileinfo)
 	{
 	{
-		auto &ti = it->second;
-		auto p = it->first;
+		auto &ti = gen->getTile(tile);
 		auto dist = ti.getNearestObjectDistance();
 		auto dist = ti.getNearestObjectDistance();
 		//avoid borders
 		//avoid borders
-		if ((p.x < 3) || (w - p.x < 3) || (p.y < 3) || (h - p.y < 3))
+		if ((tile.x < 3) || (w - tile.x < 3) || (tile.y < 3) || (h - tile.y < 3))
 			continue;
 			continue;
-		if (!ti.isBlocked()  && (dist >= min_dist) && (dist > best_distance))
+		if (gen->isPossible(tile) && (dist >= min_dist) && (dist > best_distance))
 		{
 		{
 			best_distance = dist;
 			best_distance = dist;
-			pos = p;
+			pos = tile;
+			gen->setOccupied(pos, ETileType::BLOCKED);
 			result = true;
 			result = true;
 		}
 		}
 	}
 	}
@@ -519,15 +531,15 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
 	points.insert(pos);
 	points.insert(pos);
 	for(auto const &p : points)
 	for(auto const &p : points)
 	{		
 	{		
-		if (tileinfo.find(pos + p) != tileinfo.end())
+		if (vstd::contains(tileinfo, pos + p))
 		{
 		{
-			tileinfo[pos + p].setOccupied(ETileType::USED);
+			gen->setOccupied(pos + p, ETileType::USED);
 		}
 		}
 	}
 	}
-	for(auto it = tileinfo.begin(); it != tileinfo.end(); ++it)
+	for(auto tile : tileinfo)
 	{		
 	{		
-		si32 d = pos.dist2d(it->first);
-		it->second.setNearestObjectDistance(std::min(d, it->second.getNearestObjectDistance()));
+		si32 d = pos.dist2d(tile);
+		gen->setNearestObjectDistance(tile, std::min(d, gen->getNearestObjectDistance(tile)));
 	}
 	}
 }
 }
 
 
@@ -537,32 +549,22 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
 	logGlobal->traceStream() << boost::format("Guard object at %d %d") % object->pos.x % object->pos.y;
 	logGlobal->traceStream() << boost::format("Guard object at %d %d") % object->pos.x % object->pos.y;
 	int3 visitable = object->visitablePos();
 	int3 visitable = object->visitablePos();
 	std::vector<int3> tiles;
 	std::vector<int3> tiles;
-	for(int i = -1; i < 2; ++i)
+	gen->foreach_neighbour(visitable, [&](int3& pos) 
 	{
 	{
-		for(int j = -1; j < 2; ++j)
+		logGlobal->traceStream() << boost::format("Block at %d %d") % pos.x % pos.y;
+		if (gen->isPossible(pos))
 		{
 		{
-			auto it = tileinfo.find(visitable + int3(i, j, 0));
-			if (it != tileinfo.end())
-			{
-				if (it->first != visitable)
-				{
-					logGlobal->traceStream() << boost::format("Block at %d %d") % it->first.x % it->first.y;
-					if (it->second.isPossible())
-					{
-						tiles.push_back(it->first);
-						it->second.setOccupied(ETileType::BLOCKED);
-					}
-				}
-			}
-		}
-	}
+			tiles.push_back(pos);
+			gen->setOccupied(pos, ETileType::BLOCKED);
+		};
+	});
 	if ( ! tiles.size())
 	if ( ! tiles.size())
 	{		
 	{		
 		logGlobal->infoStream() << "Failed";
 		logGlobal->infoStream() << "Failed";
 		return false;
 		return false;
 	}
 	}
 	auto guard_tile = *RandomGeneratorUtil::nextItem(tiles, gen->rand);
 	auto guard_tile = *RandomGeneratorUtil::nextItem(tiles, gen->rand);
-	tileinfo[guard_tile].setOccupied(ETileType::USED);
+	gen->setOccupied (guard_tile, ETileType::USED);
 	auto guard = new CGCreature();
 	auto guard = new CGCreature();
 	guard->ID = Obj::RANDOM_MONSTER;
 	guard->ID = Obj::RANDOM_MONSTER;
 	guard->subID = 0;
 	guard->subID = 0;

+ 2 - 1
lib/rmg/CRmgTemplateZone.h

@@ -112,6 +112,7 @@ public:
 	void addTile (const int3 &pos);
 	void addTile (const int3 &pos);
 	void setShape(std::vector<int3> shape);
 	void setShape(std::vector<int3> shape);
 	bool fill(CMapGenerator* gen);
 	bool fill(CMapGenerator* gen);
+	void createBorder(CMapGenerator* gen);
 
 
 	void addConnection(TRmgTemplateZoneId otherZone);
 	void addConnection(TRmgTemplateZoneId otherZone);
 	std::vector<TRmgTemplateZoneId> getConnections() const;
 	std::vector<TRmgTemplateZoneId> getConnections() const;
@@ -136,7 +137,7 @@ private:
 	//placement info
 	//placement info
 	int3 pos;
 	int3 pos;
 	float3 center;
 	float3 center;
-	std::map<int3, CTileInfo> tileinfo; //irregular area assined to zone
+	std::set<int3> tileinfo; //irregular area assined to zone
 	std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
 	std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
 	std::map<TRmgTemplateZoneId, bool> alreadyConnected; //TODO: allow multiple connections between two zones?
 	std::map<TRmgTemplateZoneId, bool> alreadyConnected; //TODO: allow multiple connections between two zones?