1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

First attempt to enforce curved paths

This commit is contained in:
Tomasz Zieliński 2024-11-21 22:00:24 +01:00
parent 03273ed324
commit 855ab0f0e9
5 changed files with 55 additions and 11 deletions

View File

@ -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

View File

@ -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:

View File

@ -282,20 +282,19 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
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())
{

View File

@ -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);

View File

@ -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;
}