
Introduction to A* - phenylene
http://www.redblobgames.com/pathfinding/a-star/introduction.html
======
gavanwoolery
Excellent article - I recently worked on some pathfinding stuff and the
material I found on A* was not that great but this is very well laid out.

Important side note: A* or other "best path" algorithms are not always
preferable - there are some situations where it makes sense to use even less
ideal paths in exchange for greater speed and less memory usage - even ones
that are faster than greedy-best-first search with A* shown here.

If you use recursive backtracking with a decent set of heuristics (i.e. choose
the node with the closest distance to the goal, "as the crow flies"), it can
be be fast and ideal in many situations (it will always give an ideal path
when there are few hook or concave shapes to deal with, which in many games or
applications is often the case). It can be done in linear time and memory - it
is important to note the cost of adding and searching nodes in the algorithm
as well. It will never "fail" but it will produce very bad paths sometimes in
complex situations, although even then it occasionally produces ideal paths.
In many situations where having an ideal path is not critical (say,
townspeople just walking about doing their business) this can work well. Of
course, you can use multiple algorithms or even mix them depending on what you
are trying to achieve. RBT can be a good starting point just because it is so
easy (maybe the easiest fail-safe algorithm outside of brute force?).

Secondary note: it is also good to subdivide your space - it does not need to
be something complex like a sparse octree (in fact, that will make it harder
to write and get good performance with in many situations). Rather consider
something like two levels of nodes. On a 2D map, say you were to divide it
into subsets of NxN grids of nodes. Each one of these node grids attaches to
its neighbor based on whether or not it is traversable in that direction (i.e.
no matter where you enter the node grid, there is a path out in that
direction). This allows you to easily find a "high level" path which can be
rapidly changed or discarded based on changing circumstances.

~~~
vanderZwan
> _Important side note: A_ * _or other "best path" algorithms are not always
> preferable - there are some situations where it makes sense to use even less
> ideal paths in exchange for greater speed and less memory usage - even ones
> that are faster than greedy-best-first search with A_ shown here.*

Another example is when you are dealing with large crowds. Vector fields tend
to shine there. A simple example is using a vector field when dealing with a
large swarm with one goal:

[http://gamedevelopment.tutsplus.com/tutorials/understanding-...](http://gamedevelopment.tutsplus.com/tutorials/understanding-
goal-based-vector-field-pathfinding--gamedev-9007)

Something more slightly more advanced yet incredibly powerful would be
"continuum crowds", where the agents in the swarm are also obstacles for each
other, affecting the vector field:

[https://www.youtube.com/watch?v=lGOvYyJ6r1c](https://www.youtube.com/watch?v=lGOvYyJ6r1c)

[http://grail.cs.washington.edu/projects/crowd-
flows/](http://grail.cs.washington.edu/projects/crowd-flows/)

The intriguing part here is that these potential field can have any source -
so it's relatively easy to get complex behaviour, such as pedestrians avoiding
cars, or prey/predator behaviour.

Again, these are more relavant with large crowds, so as stated before: the
best approach all depends on the particular use-case.

~~~
gavanwoolery
That is an interesting example with the fluid pathfinder - had not considered
a fluid solver for that application but it seems to work really well - even
perhaps mimicking nature. If you look at a large flock of Starlings their
movement is almost fluid-like: [http://www.youtube.com/watch?v=XH-
groCeKbE](http://www.youtube.com/watch?v=XH-groCeKbE)

~~~
raymondh
Thanks for that link. It was a marvel and a delight.

------
sjwright
It's not immediately obvious, but all the diagrams on that page are actually
live and interactive demonstrations. You can move the entities, and you can
reshape the walls as much as you like.

------
MagerValp
Since Amit's apparently here reading, great job on updating your A*
introduction (which was already excellent!), I really like how you break it
down piece by piece. While it's a very simple algorithm at its core, there are
some really subtle nuances that are easy to miss when you first approach it,
e.g. the difference between a search node and a map coordinate (assuming
classic 2D game maps).

I had some fun earlier this year implementing A* in 6502 assembler, starting
with Python and working my way down through Objective-C and C before finally
hand-optimizing the critical paths in asm. Articles are here for those who
enjoy that kind of thing:

[http://magervalp.github.io/2014/05/02/priority-queue-in-
asm....](http://magervalp.github.io/2014/05/02/priority-queue-in-asm.html)
[http://magervalp.github.io/2014/05/07/astar-in-
asm.html](http://magervalp.github.io/2014/05/07/astar-in-asm.html)

The code is available on github too:
[https://github.com/MagerValp/AsmAstar](https://github.com/MagerValp/AsmAstar)

~~~
eric_bullington
>I had some fun earlier this year implementing A* in 6502 assembler, starting
with Python and working my way down through Objective-C and C before finally
hand-optimizing the critical paths in asm.

Oh, that's a really great idea. I'm going to do that with a few interesting
algorithms now, starting with Python and working down via Rust and maybe C to
assembly.

I'm actually doing a take on that with several network clients (Stomp and
mqtt) at the present, starting with Python and then moving to Rust.

But I'm really interested now in embedded programming so I should pick a
challenging algo and work all the way down to assembly to run on bare metal.
Algorithms are nice for this type of exercise since they typically have
limited IO.

Great idea, thanks!

------
dj-wonk
Again, a great article, but I feel like some of the general thinking behind
heuristics is getting lost. Heuristics can be significantly more interesting
than distance between two points. This isn't a huge criticism. In this context
-- pathfinding on a grid -- complicated heuristics may not be needed.

When I first read about A* a long time ago I remember, for example, reading
about how static summaries of chess board positions may be useful heuristics.
Developing pieces towards the center of the board is often better, for
example. To me, seeing this was an "ah ha" moment for heuristics: use them if
they are cheap and (sometimes) informative, relative to the search cost.

~~~
gamegoblin
I once wrote an A* algorithm to solve a 15-puzzle (the thing with 15 sliding
tiles and 1 empty space, often depicting a picture, or just the numbers).

An easy heuristic that vastly improves the search: the sum of the manhattan
distances of the pieces' current locations to their final positions.

So, as you said, rather than thinking about distance only in a Euclidean
space, A* heuristics are much more general -- any metric that measures "done-
ness".

~~~
wlievens
For an AI course we had to write a solver for a puzzle using a heuristic. We
had a reference solution step count to aim towards. After many hours of
tweaking I still could not solve it. I had writ and rewritten quite
complicated heuristics but to no avail, until at one point I stumbled on a
nearly optimal solution. Upon reading my code again I noticed that a stray
parenthes and a forgivinv lisp parser had caused most of my heuristic's code
to be ignored. The simplest thing Just Worked :-)

------
raymondh
Programming nit: The posted code should use collections.deque() rather than
Queue.Queue(). The former is a high-speed C-coded datatype that is ideal for a
search queue. The latter is a pure Python wrapper that adds thread
synchronization around an underlying collections.deque() object. The wrapper
overhead is only worth it if you're actually using multiple threads that share
the same queue.

~~~
raymondh
In the author's separate page of implementation notes, a Queue class is
created that doesn't have threading overhead. That would be great, but it uses
list.pop(0) which is an O(n) operation. For O(1) performance, it should use
collections.deque.popleft() instead.

Otherwise, the article is first-rate :-)

~~~
amitp
Ah, thanks! I've been focusing on simplicity rather than performance, but
deque is just as simple here, so I should use it. :-)

------
beefsack
For those who haven't implemented A* before it can be quite an enlightening
experience, and actually isn't too difficult once you dive in. It's a good
introduction to priority queues too if you haven't played with them before.

I threw together an implentation of A* as a library in Go [1] for a game I've
been doing, it has automated tests which mock up a game world and check the
length of paths with visual output.

[1] [https://github.com/beefsack/go-astar](https://github.com/beefsack/go-
astar)

------
sgustard
An earlier version of this article by Amit was posted to HN a few months ago:

[http://theory.stanford.edu/~amitp/GameProgramming/AStarCompa...](http://theory.stanford.edu/~amitp/GameProgramming/AStarComparison.html)

~~~
scott_karana
Thanks; I thought it looked familiar, and didn't want to bookmark the same
page twice. :)

------
dj-wonk
Excellent! One suggestion. The article mentions "inadmissible heuristic" but
does not talk about what that means.

Per
[https://en.wikipedia.org/wiki/Admissible_heuristic](https://en.wikipedia.org/wiki/Admissible_heuristic),
"In computer science, specifically in algorithms related to pathfinding, a
heuristic function is said to be admissible if it never overestimates the cost
of reaching the goal, i.e. the cost it estimates to reach the goal is not
higher than the lowest possible cost from the current point in the path.[1] An
admissible heuristic is also known as an optimistic heuristic."

------
xer0x
The author, Amit Patel, makes awesome stuff! His writeup on hexagon grids is
excellent also. Plus for some retro gaming Solar Realms Elite is one of the
finest BBS door games of it's time.

------
lenocinor
Great article. This is the first A* article I've seen online that has good
visualization. I teach this in my game AI class and the visualization is key
to understanding.

------
kenshiro_o
Awesome article! The diagrams made it extremely easy for me to recall how A*
worked. I now vividly remember graph traversal theory classes an exercises
from University time!

I guess the implementation effort greatly varies depending on the programming
language and the libraries at one's disposal. However, I believe that even for
someone not too versed into data structures, the priority queue should be
relatively easy to implement.

------
jonalmeida
The visualizations are incredibly key to helping understand. It would have
been much harder for me to understand what was going on without it.

Well done!

