mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Better fitness function(s)
This commit is contained in:
parent
b52eeb2263
commit
875bfb025e
@ -103,8 +103,12 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
|
|
||||||
//remember best solution
|
//remember best solution
|
||||||
float bestTotalDistance = 1e10;
|
float bestTotalDistance = 1e10;
|
||||||
|
float bestTotalOverlap = 1e10;
|
||||||
|
//float bestRatio = 1e10;
|
||||||
std::map<CRmgTemplateZone *, float3> bestSolution;
|
std::map<CRmgTemplateZone *, float3> bestSolution;
|
||||||
|
|
||||||
|
const int maxDistanceMovementRatio = zones.size() * zones.size(); //experimental - the more zones, the greater total distance expected
|
||||||
|
|
||||||
auto getDistance = [](float distance) -> float
|
auto getDistance = [](float distance) -> float
|
||||||
{
|
{
|
||||||
return (distance ? distance * distance : 1e-6);
|
return (distance ? distance * distance : 1e-6);
|
||||||
@ -112,6 +116,7 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
|
|
||||||
std::map <CRmgTemplateZone *, float3> forces;
|
std::map <CRmgTemplateZone *, float3> forces;
|
||||||
std::map <CRmgTemplateZone *, float> distances;
|
std::map <CRmgTemplateZone *, float> distances;
|
||||||
|
std::map <CRmgTemplateZone *, float> overlaps;
|
||||||
while (zoneScale < 1) //until zones reach their desired size and fill the map tightly
|
while (zoneScale < 1) //until zones reach their desired size and fill the map tightly
|
||||||
{
|
{
|
||||||
for (auto zone : zones)
|
for (auto zone : zones)
|
||||||
@ -131,10 +136,12 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
{
|
{
|
||||||
//WARNING: compiler used to 'optimize' that line so it never actually worked
|
//WARNING: compiler used to 'optimize' that line so it never actually worked
|
||||||
forceVector += (((otherZoneCenter - pos)*(pos.z != otherZoneCenter.z ? (distance - minDistance) : 1)/ getDistance(distance))); //positive value
|
forceVector += (((otherZoneCenter - pos)*(pos.z != otherZoneCenter.z ? (distance - minDistance) : 1)/ getDistance(distance))); //positive value
|
||||||
totalDistance += distance;
|
totalDistance += (distance - minDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
distances[zone.second] = totalDistance;
|
distances[zone.second] = totalDistance;
|
||||||
|
|
||||||
|
float totalOverlap = 0;
|
||||||
//separate overlaping zones
|
//separate overlaping zones
|
||||||
for (auto otherZone : zones)
|
for (auto otherZone : zones)
|
||||||
{
|
{
|
||||||
@ -148,8 +155,10 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
if (distance < minDistance)
|
if (distance < minDistance)
|
||||||
{
|
{
|
||||||
forceVector -= (((otherZoneCenter - pos)*(minDistance - distance)) / getDistance(distance)); //negative value
|
forceVector -= (((otherZoneCenter - pos)*(minDistance - distance)) / getDistance(distance)); //negative value
|
||||||
|
totalOverlap += (minDistance - distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
overlaps[zone.second] = totalOverlap;
|
||||||
|
|
||||||
//move zones away from boundaries
|
//move zones away from boundaries
|
||||||
//do not scale boundary distance - zones tend to get squashed
|
//do not scale boundary distance - zones tend to get squashed
|
||||||
@ -192,28 +201,39 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
CRmgTemplateZone * distantZone = nullptr;
|
CRmgTemplateZone * distantZone = nullptr;
|
||||||
|
|
||||||
float totalDistance = 0;
|
float totalDistance = 0;
|
||||||
|
float totalOverlap = 0;
|
||||||
for (auto zone : distances) //find most misplaced zone
|
for (auto zone : distances) //find most misplaced zone
|
||||||
{
|
{
|
||||||
totalDistance += zone.second;
|
totalDistance += zone.second;
|
||||||
float ratio = zone.second / forces[zone.first].mag(); //if distance to actual movement is long, the zone is misplaced
|
int overlap = overlaps[zone.first];
|
||||||
|
totalOverlap += overlap;
|
||||||
|
float ratio = (zone.second + overlap) / forces[zone.first].mag(); //if distance to actual movement is long, the zone is misplaced
|
||||||
if (ratio > maxRatio)
|
if (ratio > maxRatio)
|
||||||
{
|
{
|
||||||
maxRatio = ratio;
|
maxRatio = ratio;
|
||||||
distantZone = zone.first;
|
distantZone = zone.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logGlobal->traceStream() << boost::format("Total distance between zones in this iteration: %2.2f, Worst distance/movement ratio: %3.2f") % totalDistance % maxRatio;
|
logGlobal->traceStream() << boost::format("Total distance between zones in this iteration: %2.4f, Total overlap: %2.4f, Worst misplacement/movement ratio: %3.2f") % totalDistance % totalOverlap % maxRatio;
|
||||||
|
|
||||||
//save best solution before drastic jump
|
//save best solution before drastic jump
|
||||||
if (totalDistance < bestTotalDistance)
|
if (totalDistance <= bestTotalDistance && totalOverlap <= bestTotalOverlap)
|
||||||
{
|
{
|
||||||
bestTotalDistance = totalDistance;
|
bestTotalDistance = totalDistance;
|
||||||
|
bestTotalOverlap = totalOverlap;
|
||||||
|
//if (maxRatio < bestRatio)
|
||||||
|
//{
|
||||||
|
// bestRatio = maxRatio;
|
||||||
for (auto zone : zones)
|
for (auto zone : zones)
|
||||||
bestSolution[zone.second] = zone.second->getCenter();
|
bestSolution[zone.second] = zone.second->getCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxRatio > 100)
|
if (maxRatio > maxDistanceMovementRatio)
|
||||||
{
|
{
|
||||||
|
//simply move the zone further in same direction
|
||||||
|
//distantZone->setCenter(distantZone->getCenter() + forces[distantZone] * maxRatio / maxDistanceMovementRatio);
|
||||||
|
//logGlobal->traceStream() << boost::format("Trying to move zone %d %s further") % distantZone->getId() % distantZone->getCenter()();
|
||||||
|
|
||||||
//find most distant zone that should be attracted and move inside it
|
//find most distant zone that should be attracted and move inside it
|
||||||
|
|
||||||
CRmgTemplateZone * targetZone = nullptr;
|
CRmgTemplateZone * targetZone = nullptr;
|
||||||
@ -237,10 +257,14 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
|
|
||||||
distantZone->setCenter(targetZone->getCenter() - vec.unitVector() * newDistanceBetweenZones); //zones should now overlap by half size
|
distantZone->setCenter(targetZone->getCenter() - vec.unitVector() * newDistanceBetweenZones); //zones should now overlap by half size
|
||||||
logGlobal->traceStream() << boost::format("New distance %f") % targetZone->getCenter().dist2d(distantZone->getCenter());
|
logGlobal->traceStream() << boost::format("New distance %f") % targetZone->getCenter().dist2d(distantZone->getCenter());
|
||||||
|
|
||||||
|
//TODO: do the same with overlapping zones?
|
||||||
}
|
}
|
||||||
|
|
||||||
zoneScale *= inflateModifier; //increase size of zones so they
|
zoneScale *= inflateModifier; //increase size of zones so they
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logGlobal->traceStream() << boost::format("Best fitness reached: total distance %2.4f, total overlap %2.4f") % bestTotalDistance % bestTotalOverlap;
|
||||||
for (auto zone : zones) //finalize zone positions
|
for (auto zone : zones) //finalize zone positions
|
||||||
{
|
{
|
||||||
zone.second->setPos (cords (bestSolution[zone.second]));
|
zone.second->setPos (cords (bestSolution[zone.second]));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user