5

I'm working on A* pathfinding for a grid based top-down game. The issue I've came across is probably easiest to understand in the image below. Asterisks are players/NPCs. The yellow asterisk is the current NPC that wants to path to the X. The red asterisks are NPCs that in this case are obstacles. Yellow cells are walls, white cells are floor. While the entire path to the goal is indeed unreachable, I'm still wanting to get a path to the next best location (in this case, spot numbered 8).

I can easily have it path around obstacles, but not sure how to do exactly as I describe. If I stop it once it's hit an obstacle, it doesn't perform properly by stopping at 3. If I re-path to the tile in the closed list with the lowest distance from the end goal, if the end goal is on the other side of a wall as an example it can mess things up quite bad as well.

Any suggestions? I feel like I'm missing something otherwise obvious, so please forgive an idiocy here.

enter image description here

Thanks, Tim

Mythics
  • 773
  • 1
  • 10
  • 19
  • The easy solution is to keep track of the best path so far in the A* loop and just keep searching until you either find the X or have exhausted the search space, then return the best path found. – Fred Foo Oct 25 '12 at 14:56
  • It is not really clear to me what is being asked here. What is currently happening and what do you want to happen? – Dialecticus Oct 25 '12 at 14:59
  • @larsmans - To determine "the best path so far", I assume to keep track of the path that gets closest to the end point. If the end point is on the other side of a wall, like the additional image, 2 would be the stopping point unless I'm missing something. – Mythics Oct 25 '12 at 15:06
  • @TimWinter: I was thinking out loud :) Let me try to formulate a more precise answer. – Fred Foo Oct 25 '12 at 15:10
  • @Dialecticus - In either image above, the goal is unreachable. I want my pathfinding to still find the best path, even when the end goal is unreachable. My first attempt at this was to stop when it hits a NPC/Asterisk, but that is VERY flawed. If I instead try to have it do the full path, see it fails, then pull the path to the node that was closest to the goal. That is also flawed, as the second example would show (it'd stop at 2). The question is then, how to use A* to path around obstacles towards a goal, but still spit out what the path would be if the full blocking obstacles didn't exist. – Mythics Oct 25 '12 at 15:13
  • Would it make sense to just set a hefty weight on occupied tiles, then when building the path from the closed list, stop if it actually hits an obstacle? – Mythics Oct 25 '12 at 15:15

2 Answers2

7

Here's an idea, based on problem relaxation:

First, solve the shortest-path problem for all vertices of a graph that has no NPCs. You can use a single application of Dijkstra's algorithm starting from the goal node to get the shortest path to/from the goal at each vertex.

Then attempt to find the shortest path in the full problem. Use A* with the shortest path information obtained by running Dijkstra's as the heuristic; it's admissible as the shortest path in the problem with NPCs is always at least as long as the shortest path in the relaxed problem. Keep track of the best path so far and return that when the search space is exhausted (as I posted in the comment).

If you think this is expensive, then realize that you only have to run Dijkstra's once; you can reuse the information obtained for each run of A* on the same graph.

(Caveat emptor: I didn't try any of this out.)

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
0

One method would be to calculate the path from source to destination without taking blocking NPCs into account, then checking if there's any blocking NPC directly on the path. If so, take the first blocking NPC on the path into account, then calculate the path again. Rinse and repeat until you can't get to the destination anymore. When this happens, you can take the point just before the latest blocking NPC on the last successful path as the "next best" destination.

This should work well for your examples, but if there would be two blocked entrances to the destination, this method would go for the entrance that's further away. Also, in the worst case, you'd have to run the shortest path algorithm as many times as there are NPCs.

The method presented by larsmans is way better than this, since you only have to run Dijkstra and A* once. I only present this as an idea of the kinds of approaches you can take.

Aleksi Torhamo
  • 6,452
  • 2
  • 34
  • 44