Add a hack in the pathfinder to pick more diagonal paths
This was SVN commit r7295.
This commit is contained in:
parent
1678055edd
commit
fa1fd65a3e
@ -460,23 +460,55 @@ static void ProcessNeighbour(u16 pi, u16 pj, u16 i, u16 j, u32 pg, PriorityQueue
|
|||||||
if (terrainGrid->get(i, j))
|
if (terrainGrid->get(i, j))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u32 cost = pg + g_CostPerTile;
|
// Calculate the cost of moving from predecessor to here
|
||||||
// TODO: should use terrain costs etc
|
u32 dg = g_CostPerTile;
|
||||||
|
|
||||||
|
// Calculate heuristic cost to target
|
||||||
|
// (This ought to be an underestimate for correctness)
|
||||||
u32 h = (abs((int)i - (int)i1) + abs((int)j - (int)j1)) * g_CostPerTile;
|
u32 h = (abs((int)i - (int)i1) + abs((int)j - (int)j1)) * g_CostPerTile;
|
||||||
|
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
// XXX: Terrible hack:
|
||||||
|
// For simplicity, we only consider horizontally/vertically adjacent neighbours, but
|
||||||
|
// units can move along arbitrary lines. That results in ugly square paths, so we want
|
||||||
|
// to prefer diagonal paths.
|
||||||
|
// Instead of solving this nicely, I'll just special-case 45-degree and 30-degree lines
|
||||||
|
// by checking the three predecessor tiles (which'll be in the closed set and therefore
|
||||||
|
// likely to be reasonably stable) and reduce the cost, and use a Euclidean heuristic.
|
||||||
|
// At least this makes paths look a bit nicer for now...
|
||||||
|
|
||||||
|
PathfindTile& p = tempGrid->get(pi, pj);
|
||||||
|
if (p.pi != i && p.pj != j)
|
||||||
|
dg = dg*(sqrt(2.0)/2.0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PathfindTile& pp = tempGrid->get(p.pi, p.pj);
|
||||||
|
int di = abs(i - pp.pi);
|
||||||
|
int dj = abs(j - pp.pj);
|
||||||
|
if ((di == 1 && dj == 2) || (di == 2 && dj == 1))
|
||||||
|
dg = dg*(sqrt(5.0)-sqrt(2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
h = hypot(i-i1, j-j1)*g_CostPerTile;
|
||||||
|
// XXX: shouldn't use floats here
|
||||||
|
// Also, the heuristic should match the costs better
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 g = pg + dg;
|
||||||
|
|
||||||
PathfindTile& n = tempGrid->get(i, j);
|
PathfindTile& n = tempGrid->get(i, j);
|
||||||
|
|
||||||
// If we've already added this tile to the open list:
|
// If we've already added this tile to the open list:
|
||||||
if (n.status == PathfindTile::STATUS_OPEN)
|
if (n.status == PathfindTile::STATUS_OPEN)
|
||||||
{
|
{
|
||||||
// If this a better path, replace the old one with the new cost/parent
|
// If this a better path, replace the old one with the new cost/parent
|
||||||
if (cost < n.cost)
|
if (g < n.cost)
|
||||||
{
|
{
|
||||||
n.cost = cost;
|
n.cost = g;
|
||||||
n.pi = pi;
|
n.pi = pi;
|
||||||
n.pj = pj;
|
n.pj = pj;
|
||||||
open.find(i, j)->rank = cost + h;
|
open.find(i, j)->rank = g + h;
|
||||||
open.fixheap(); // XXX: this is slow
|
open.fixheap(); // XXX: this is slow
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -486,7 +518,7 @@ static void ProcessNeighbour(u16 pi, u16 pj, u16 i, u16 j, u32 pg, PriorityQueue
|
|||||||
if (n.status == PathfindTile::STATUS_CLOSED)
|
if (n.status == PathfindTile::STATUS_CLOSED)
|
||||||
{
|
{
|
||||||
// If this is a better path (possible when we use inadmissible heuristics), reopen it
|
// If this is a better path (possible when we use inadmissible heuristics), reopen it
|
||||||
if (cost < n.cost)
|
if (g < n.cost)
|
||||||
{
|
{
|
||||||
closed.remove(i, j);
|
closed.remove(i, j);
|
||||||
// (don't return yet)
|
// (don't return yet)
|
||||||
@ -499,10 +531,10 @@ static void ProcessNeighbour(u16 pi, u16 pj, u16 i, u16 j, u32 pg, PriorityQueue
|
|||||||
|
|
||||||
// Add it to the open list:
|
// Add it to the open list:
|
||||||
n.status = PathfindTile::STATUS_OPEN;
|
n.status = PathfindTile::STATUS_OPEN;
|
||||||
n.cost = cost;
|
n.cost = g;
|
||||||
n.pi = pi;
|
n.pi = pi;
|
||||||
n.pj = pj;
|
n.pj = pj;
|
||||||
QueueItem t = { i, j, cost + h };
|
QueueItem t = { i, j, g + h };
|
||||||
open.push(t);
|
open.push(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,6 +556,9 @@ void CCmpPathfinder::ComputePath(entity_pos_t x0, entity_pos_t z0, entity_pos_t
|
|||||||
QueueItem start = { i0, j0, 0 };
|
QueueItem start = { i0, j0, 0 };
|
||||||
open.push(start);
|
open.push(start);
|
||||||
tempGrid->get(i0, j0).status = PathfindTile::STATUS_OPEN;
|
tempGrid->get(i0, j0).status = PathfindTile::STATUS_OPEN;
|
||||||
|
tempGrid->get(i0, j0).pi = i0;
|
||||||
|
tempGrid->get(i0, j0).pj = j0;
|
||||||
|
tempGrid->get(i0, j0).cost = 0;
|
||||||
|
|
||||||
u16 ip = i0, jp = j0; // the last tile on the path to the destination
|
u16 ip = i0, jp = j0; // the last tile on the path to the destination
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user