Pārlūkot izejas kodu

First attempt to enforce curved paths

Tomasz Zieliński 11 mēneši atpakaļ
vecāks
revīzija
855ab0f0e9

+ 20 - 0
lib/rmg/RmgPath.cpp

@@ -190,4 +190,24 @@ const Area & Path::getPathArea() const
 	return dPath;
 }
 
+Path::MoveCostFunction Path::createCurvedCostFunction(const Area & border)
+{
+	// Capture by value to ensure the Area object persists
+	return [border = border](const int3& src, const int3& dst) -> float
+	{
+		// Route main roads far from border
+		//float ret = dst.dist2d(src);
+		float ret = dst.dist2d(src);
+
+		float dist = border.distanceSqr(dst);
+		//int3 closestTile = border.nearest(dst);
+		//float dist = dst.chebdist2d(closestTile);
+		if(dist > 1.0f)
+		{
+			ret /= dist * dist;
+		}
+		return ret;
+	};
+}
+
 VCMI_LIB_NAMESPACE_END

+ 3 - 1
lib/rmg/RmgPath.h

@@ -21,7 +21,8 @@ namespace rmg
 class Path
 {
 public:
-	const static std::function<float(const int3 &, const int3 &)> DEFAULT_MOVEMENT_FUNCTION;
+	typedef std::function<float(const int3 &, const int3 &)> MoveCostFunction;
+	const static MoveCostFunction DEFAULT_MOVEMENT_FUNCTION;
 	
 	Path(const Area & area);
 	Path(const Area & area, const int3 & src);
@@ -42,6 +43,7 @@ public:
 	const Area & getPathArea() const;
 	
 	static Path invalid();
+	static MoveCostFunction createCurvedCostFunction(const Area & border);
 	
 private:
 	

+ 8 - 9
lib/rmg/modificators/ConnectionsPlacer.cpp

@@ -278,24 +278,23 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
 			assert(zone.getModificator<ObjectManager>());
 			auto & manager = *zone.getModificator<ObjectManager>();
 			auto * monsterType = manager.chooseGuard(connection.getGuardStrength(), true);
-			
+		
 			rmg::Area border(zone.area()->getBorder());
 			border.unite(otherZone->area()->getBorder());
-			
-			auto costFunction = [&border](const int3 & s, const int3 & d)
-			{
-				return 1.f / (1.f + border.distanceSqr(d));
-			};
-			
+
+			auto localCostFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());
+			auto otherCostFunction = rmg::Path::createCurvedCostFunction(otherZone->area()->getBorder());
+
+			// TODO: helper function for this sum?
 			auto ourArea = zone.areaPossible() + zone.freePaths();
 			auto theirArea = otherZone->areaPossible() + otherZone->freePaths();
 			theirArea.add(guardPos);
 			rmg::Path ourPath(ourArea);
 			rmg::Path theirPath(theirArea);
 			ourPath.connect(zone.freePaths().get());
-			ourPath = ourPath.search(guardPos, true, costFunction);
+			ourPath = ourPath.search(guardPos, true, localCostFunction);
 			theirPath.connect(otherZone->freePaths().get());
-			theirPath = theirPath.search(guardPos, true, costFunction);
+			theirPath = theirPath.search(guardPos, true, otherCostFunction);
 			
 			if(ourPath.valid() && theirPath.valid())
 			{

+ 23 - 0
lib/rmg/modificators/ObjectManager.cpp

@@ -419,6 +419,11 @@ bool ObjectManager::createMonoliths()
 			return false;
 		}
 		
+		// Once it can be created, replace with curved path
+		auto costFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());	
+		rmg::Path curvedPath(zone.areaPossible() + zone.freePaths());
+		path = curvedPath.search(rmgObject.getVisitablePosition(), true, costFunction);
+		
 		zone.connectPath(path);
 		placeObject(rmgObject, guarded, true, objInfo.createRoad);
 	}
@@ -449,6 +454,24 @@ bool ObjectManager::createRequiredObjects()
 			logGlobal->error("Failed to fill zone %d due to lack of space", zone.getId());
 			return false;
 		}
+		if (objInfo.createRoad)
+		{
+			// Once valid path can be created, replace with curved path
+
+			auto costFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());
+			auto pathArea = zone.areaPossible() + zone.freePaths();
+			rmg::Path curvedPath(pathArea);
+			curvedPath.connect(zone.freePaths().get());
+			curvedPath = curvedPath.search(rmgObject.getVisitablePosition(), false, costFunction);
+			if (curvedPath.valid())
+			{
+				path = curvedPath;
+			}
+			else
+			{
+				logGlobal->warn("Failed to create curved path for required object at %s", rmgObject.getPosition().toString());
+			}
+		}
 		
 		zone.connectPath(path);
 		placeObject(rmgObject, guarded, true, objInfo.createRoad);

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

@@ -91,7 +91,7 @@ bool RoadPlacer::createRoad(const int3 & destination)
 			float dist = border.distanceSqr(dst);
 			if(dist > 1.0f)
 			{
-				ret /= dist;
+				ret /= dist * dist;
 			}
 			return ret;
 		}