Skip to content

Commit

Permalink
fix #5947
Browse files Browse the repository at this point in the history
  • Loading branch information
rt committed Apr 2, 2018
1 parent c2fb732 commit 58d4066
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 41 deletions.
20 changes: 4 additions & 16 deletions rts/Sim/MoveTypes/MoveMath/MoveMath.cpp
Expand Up @@ -114,18 +114,13 @@ CMoveMath::BlockType CMoveMath::IsBlockedNoSpeedModCheck(const MoveDef& moveDef,
const int xmax = std::min(xSquare + moveDef.xsizeh, mapDims.mapx - 1);
const int zmax = std::min(zSquare + moveDef.zsizeh, mapDims.mapy - 1);

#if 0
if (xmin < 0 || xmax >= mapDims.mapx)
return BLOCK_IMPASSABLE;
if (zmin < 0 || zmax >= mapDims.mapy)
return BLOCK_IMPASSABLE;
#endif

BlockType ret = BLOCK_NONE;

// (footprints are point-symmetric around <xSquare, zSquare>)
// footprints are point-symmetric around <xSquare, zSquare>
// same as RangeIsBlocked but without anti-duplication test
for (int z = zmin; z <= zmax; z += FOOTPRINT_ZSTEP) {
const int zOffset = z * mapDims.mapx;

for (int x = xmin; x <= xmax; x += FOOTPRINT_XSTEP) {
const BlockingMapCell& cell = groundBlockingObjectMap.GetCellUnsafeConst(zOffset + x);

Expand Down Expand Up @@ -272,23 +267,16 @@ CMoveMath::BlockType CMoveMath::SquareIsBlocked(const MoveDef& moveDef, int xSqu

CMoveMath::BlockType CMoveMath::RangeIsBlocked(const MoveDef& moveDef, int xmin, int xmax, int zmin, int zmax, const CSolidObject* collider)
{
#if 0
if (xmin < 0 || xmax >= mapDims.mapx)
return BLOCK_IMPASSABLE;
if (zmin < 0 || zmax >= mapDims.mapy)
return BLOCK_IMPASSABLE;
#else
xmin = std::max(xmin, 0);
zmin = std::max(zmin, 0);
xmax = std::min(xmax, mapDims.mapx - 1);
zmax = std::min(zmax, mapDims.mapy - 1);
#endif

BlockType ret = BLOCK_NONE;

const int tempNum = gs->GetTempNum();

// (footprints are point-symmetric around <xSquare, zSquare>)
// footprints are point-symmetric around <xSquare, zSquare>
for (int z = zmin; z <= zmax; z += FOOTPRINT_ZSTEP) {
const int zOffset = z * mapDims.mapx;

Expand Down
2 changes: 1 addition & 1 deletion rts/Sim/Path/Default/PathConstants.h
Expand Up @@ -26,7 +26,7 @@ static const float MEDRES_SEARCH_DISTANCE_EXT = (MEDRES_SEARCH_DISTANCE * 0.4f)
// how many recursive refinement attempts NextWayPoint should make
static constexpr unsigned int MAX_PATH_REFINEMENT_DEPTH = 4;

static constexpr unsigned int PATHESTIMATOR_VERSION = 91;
static constexpr unsigned int PATHESTIMATOR_VERSION = 92;

static constexpr unsigned int MEDRES_PE_BLOCKSIZE = 16;
static constexpr unsigned int LOWRES_PE_BLOCKSIZE = 32;
Expand Down
74 changes: 50 additions & 24 deletions rts/Sim/Path/Default/PathFinder.cpp
Expand Up @@ -202,7 +202,7 @@ IPath::SearchResult CPathFinder::DoSearch(

while (!openBlocks.empty() && (openBlockBuffer.GetSize() < maxBlocksToBeSearched)) {
// get the open square with lowest expected path-cost
PathNode* openSquare = const_cast<PathNode*>(openBlocks.top());
const PathNode* openSquare = openBlocks.top();
openBlocks.pop();

// check if this PathNode has become obsolete
Expand Down Expand Up @@ -250,30 +250,38 @@ void CPathFinder::TestNeighborSquares(
struct SquareState {
CMoveMath::BlockType blockMask = CMoveMath::BLOCK_IMPASSABLE;
float speedMod = 0.0f;
bool inSearch = false;
bool insideMap = true;
bool insideDef = false;
};

SquareState ngbStates[PATH_DIRECTIONS];

const int2 squarePos = square->nodePos;

const bool startSquareExpanded = (openBlocks.empty() && testedBlocks < 8);
const bool startSquareBlocked = (startSquareExpanded && (blockCheckFunc(moveDef, squarePos.x, squarePos.y, owner) & CMoveMath::BLOCK_STRUCTURE) != 0);

// precompute structure-blocked state and speedmod for all neighbors
for (unsigned int dir = 0; dir < PATH_DIRECTIONS; dir++) {
const unsigned int optDir = PathDir2PathOpt(dir);
const int2 ngbSquareCoors = square->nodePos + PF_DIRECTION_VECTORS_2D[optDir];
for (SquareState& sqState: ngbStates) {
const unsigned int dirIdx = &sqState - &ngbStates[0];
const unsigned int optDir = PathDir2PathOpt(dirIdx);
const int2 ngbSquareCoors = squarePos + PF_DIRECTION_VECTORS_2D[optDir];
const unsigned int ngbSquareIdx = BlockPosToIdx(ngbSquareCoors);

if (static_cast<unsigned>(ngbSquareCoors.x) >= nbrOfBlocks.x || static_cast<unsigned>(ngbSquareCoors.y) >= nbrOfBlocks.y)
sqState.insideMap &= (static_cast<unsigned int>(ngbSquareCoors.x) < nbrOfBlocks.x);
sqState.insideMap &= (static_cast<unsigned int>(ngbSquareCoors.y) < nbrOfBlocks.y);

if (!sqState.insideMap)
continue;

if (blockStates.nodeMask[ngbSquareIdx] & (PATHOPT_CLOSED | PATHOPT_BLOCKED)) //FIXME
continue;

SquareState& sqState = ngbStates[dir];

// IsBlockedNoSpeedModCheck; very expensive call
// IsBlockedNoSpeedModCheck; very expensive call but with a ~20% (?) chance of early-out
if ((sqState.blockMask = blockCheckFunc(moveDef, ngbSquareCoors.x, ngbSquareCoors.y, owner)) & CMoveMath::BLOCK_STRUCTURE) {
blockStates.nodeMask[ngbSquareIdx] |= PATHOPT_CLOSED;
dirtyBlocks.push_back(ngbSquareIdx);
continue; // early-out (20% chance)
continue;
}


Expand All @@ -285,19 +293,32 @@ void CPathFinder::TestNeighborSquares(
// no gain placing this in front of the above code, only has a ~2%
// chance (heavily depending on the map) to early-out
//
// only close node if search is directionally independent, otherwise
// it is possible we might enter it from another (better) direction
// only close node if search is directionally independent, since it
// might still be entered from another (better) direction otherwise
if ((sqState.speedMod = CMoveMath::GetPosSpeedMod(moveDef, ngbSquareCoors.x, ngbSquareCoors.y)) == 0.0f) {
blockStates.nodeMask[ngbSquareIdx] |= PATHOPT_CLOSED;
dirtyBlocks.push_back(ngbSquareIdx);
}
}

sqState.inSearch = (sqState.speedMod != 0.0f && pfDef.WithinConstraints(ngbSquareCoors.x, ngbSquareCoors.y));
// LHS is only here to save some cycles
sqState.insideDef = (sqState.speedMod != 0.0f && pfDef.WithinConstraints(ngbSquareCoors.x, ngbSquareCoors.y));
}


const auto CanTestSquareSM = [&](const int dir) { return (ngbStates[dir].speedMod != 0.0f); };
const auto CanTestSquareIS = [&](const int dir) { return (ngbStates[dir].inSearch); };
const auto CanTestSquareIS = [&](const int dir) { return (ngbStates[dir].insideDef ); };

#if ENABLE_DIAG_TESTS
const auto TestDiagSquare = [&](const int dirX, const int dirY, const int dirXY) {
if (!CanTestSquareSM(dirXY) || (!startSquareBlocked && (!CanTestSquareSM(dirX) || !CanTestSquareSM(dirY))))
return;
if (!CanTestSquareIS(dirXY) && ( !CanTestSquareIS(dirX) || !CanTestSquareIS(dirY)))
return;

TestBlock(moveDef, pfDef, square, owner, PathDir2PathOpt(dirXY), ngbStates[dirXY].blockMask, ngbStates[dirXY].speedMod);
};
#endif

// first test squares along the cardinal directions
for (unsigned int dir: PATHDIR_CARDINALS) {
Expand All @@ -313,7 +334,8 @@ void CPathFinder::TestNeighborSquares(
// don't search diagonally if there is a blocking object
// (or blocking terrain!) in one of the two side squares
// e.g. do not consider the edge (p, q) passable if X is
// impassable in this situation:
// blocked here:
//
// +---+---+
// | X | q |
// +---+---+
Expand All @@ -327,15 +349,19 @@ void CPathFinder::TestNeighborSquares(
// edge passable since we still need to be able to jump to
// diagonally adjacent PE-blocks!
//
const auto TestDiagSquare = [&](const int dirX, const int dirY, const int dirXY) {
if (!CanTestSquareSM(dirXY) || !CanTestSquareSM(dirX) || !CanTestSquareSM(dirY))
return;
if (!CanTestSquareIS(dirXY) && (!CanTestSquareIS(dirX) || !CanTestSquareIS(dirY)))
return;

TestBlock(moveDef, pfDef, square, owner, PathDir2PathOpt(dirXY), ngbStates[dirXY].blockMask, ngbStates[dirXY].speedMod);
};

// make another exception if the starting square is inside
// a concave corner s.t. all non-diagonal ngbs are blocked
// (according to blockCheckFunc) and the MoveDef footprint
// overlaps at least one impassable square, which would be
// the case for a 5x5 footprint centered on S below
//
// [.][.][.][.][X][X]
// [.][.][.][.][X][X]
// [.][.][S][.][.][ ]
// [.][.][.][.][.][ ]
// [X][X][.][.][X][X]
// [X][X][ ][ ][X][X]
//
TestDiagSquare(PATHDIR_LEFT, PATHDIR_UP, PATHDIR_LEFT_UP );
TestDiagSquare(PATHDIR_RIGHT, PATHDIR_UP, PATHDIR_RIGHT_UP );
TestDiagSquare(PATHDIR_LEFT, PATHDIR_DOWN, PATHDIR_LEFT_DOWN );
Expand Down

0 comments on commit 58d4066

Please sign in to comment.