Browse Source

Refactor FindClosestValidPosition to use Crawl

pull/4908/head
Vladimir Olteanu 4 years ago committed by Anders Jenbo
parent
commit
f463f08642
  1. 138
      Source/engine/path.cpp

138
Source/engine/path.cpp

@ -8,6 +8,7 @@
#include <array>
#include "levels/gendung.h"
#include "lighting.h"
#include "objects.h"
namespace devilution {
@ -435,139 +436,12 @@ bool path_solid_pieces(Point startPosition, Point destinationPosition)
std::optional<Point> FindClosestValidPosition(const std::function<bool(Point)> &posOk, Point startingPosition, unsigned int minimumRadius, unsigned int maximumRadius)
{
if (minimumRadius > maximumRadius) {
return {}; // No valid search space with the given params.
}
if (minimumRadius == 0U) {
if (posOk(startingPosition)) {
return startingPosition;
}
}
if (minimumRadius <= 1U && maximumRadius >= 1U) {
// unrolling the case for radius 1 to save having to guard the corner check in the loop below.
Point candidatePosition = startingPosition + Direction::SouthWest;
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Direction::NorthEast;
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Direction::NorthWest;
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Direction::SouthEast;
if (posOk(candidatePosition)) {
return Crawl(minimumRadius, maximumRadius, [&](auto displacement) -> std::optional<Point> {
Point candidatePosition = startingPosition + displacement;
if (posOk(candidatePosition))
return candidatePosition;
}
}
if (maximumRadius >= 2U) {
for (int i = static_cast<int>(std::max(minimumRadius, 2U)); i <= static_cast<int>(std::min(maximumRadius, 50U)); i++) {
int x = 0;
int y = i;
// special case the checks when x == 0 to save checking the same tiles twice
Point candidatePosition = startingPosition + Displacement { x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
while (x < i - 1) {
x++;
candidatePosition = startingPosition + Displacement { -x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { -x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
}
// special case for inset corners
y--;
candidatePosition = startingPosition + Displacement { -x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { -x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
x++;
while (y > 0) {
candidatePosition = startingPosition + Displacement { -x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { -x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, -y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
y--;
}
// as above, special case for y == 0
candidatePosition = startingPosition + Displacement { -x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
candidatePosition = startingPosition + Displacement { x, y };
if (posOk(candidatePosition)) {
return candidatePosition;
}
}
}
return {};
return {};
});
}
#ifdef BUILD_TESTING

Loading…
Cancel
Save