Browse Source

Solution suggested by ChatGPT

Tomasz Zieliński 7 months ago
parent
commit
58041ee123
3 changed files with 45 additions and 12 deletions
  1. 39 11
      lib/rmg/RmgPath.cpp
  2. 3 0
      lib/rmg/RmgPath.h
  3. 3 1
      lib/rmg/modificators/RoadPlacer.cpp

+ 39 - 11
lib/rmg/RmgPath.cpp

@@ -190,6 +190,43 @@ const Area & Path::getPathArea() const
 	return dPath;
 }
 
+float Path::nonEuclideanCostFunction(const int3& src, const int3& dst)
+{
+	// Use non-euclidean metric
+	int dx = std::abs(src.x - dst.x);
+	int dy = std::abs(src.y - dst.y);
+	// int dx = src.x - dst.x;
+	// int dy = src.y - dst.y;
+	return std::sqrt(dx * dx + dy * dy) -
+		500 * std::sin(dx * dy / 20);
+}
+
+float Path::curvedCost(const int3& src, const int3& dst, const int3& center)
+{
+	float R = 30.0f; // radius of the zone
+	float W = 10.0f;// width of the transition area
+	float A = 0.7f; // sine bias
+
+    // Euclidean step distance:
+    float dx = dst.x - src.x;
+    float dy = dst.y - src.y;
+    float d = std::sqrt(dx*dx + dy*dy);
+    
+    // Distance from dst to the zone center:
+    float rx = dst.x - center.x;
+    float ry = dst.y - center.y;
+    float r = std::sqrt(rx*rx + ry*ry);
+    
+    // Compute normalized offset inside the zone:
+    // (R - W) is the inner edge, R is the outer edge.
+    float t = std::clamp((r - (R - W)) / W, 0.0f, 1.0f);
+    
+    // Use sine bias: lowest cost in the middle (t=0.5), higher near edges.
+    float bias = 1.0f + A * std::sin(M_PI * t);
+    
+    return d * bias;
+}
+
 Path::MoveCostFunction Path::createCurvedCostFunction(const Area & border)
 {
 	// Capture by value to ensure the Area object persists
@@ -198,17 +235,8 @@ Path::MoveCostFunction Path::createCurvedCostFunction(const Area & border)
 		// Route main roads far from border
 		//float ret = dst.dist2d(src);
 
-		auto costFunction = [border](const int3& src, const int3& dst) -> float
-		{
-			// Use non-euclidean metric
-			int dx = std::abs(src.x - dst.x);
-			int dy = std::abs(src.y - dst.y);
-			// int dx = src.x - dst.x;
-			// int dy = src.y - dst.y;
-			return std::sqrt(dx * dx + dy * dy) -
-				500 * std::sin(dx * dy / 20);
-		};
-		float ret = costFunction(src, dst);
+		//float ret = nonEuclideanCostFunction(src, dst);
+		float ret = curvedCost(src, dst, border.getCenterOfMass());
 		float dist = border.distanceSqr(dst);
 
 		if(dist > 1.0f)

+ 3 - 0
lib/rmg/RmgPath.h

@@ -18,6 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 namespace rmg
 {
+
 class Path
 {
 public:
@@ -43,6 +44,8 @@ public:
 	const Area & getPathArea() const;
 	
 	static Path invalid();
+	static float nonEuclideanCostFunction(const int3& src, const int3& dst);
+	static float curvedCost(const int3& src, const int3& dst, const int3& center);
 	static MoveCostFunction createCurvedCostFunction(const Area & border);
 	
 private:

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

@@ -93,7 +93,9 @@ bool RoadPlacer::createRoad(const int3 & destination)
 			}
 		}
 
-		float ret = dst.dist2d(src);
+		//float ret = dst.dist2d(src);
+		//float ret = rmg::Path::nonEuclideanCostFunction(src, dst);
+		float ret = rmg::Path::curvedCost(src, dst, border.getCenterOfMass());
 
 		if (visitableTiles.contains(src) || visitableTiles.contains(dst))
 		{