 |
Prisoner AI
|
 |
One thing was clear: no traditional simple rules for walking and turning would
make the prisoners head for the exit in any realistic manner. They would need
help somehow. I got the idea from a Digital Image Processing course I took a few
years ago.
Take a digital, binary image of a simple object. An elementary operation in Image
Processing is determining the generalized radius. To begin with, all boundary
points are located and marked with a value corresponding to a distance of 1 pixel
from the edge. Next, all pixels neighboring those marked ones are marked too, with
a value one step higher, and so on. Eventually each pixel has a value corresponding
to its distance from the edge. The maximum value inside the object is its radius.

An interesting side effect is that, given these values, there is now an incredibly
simple strategy for finding the shortest route from any pixel to the edge. Just
look at the surrounding pixels up, down, left and right and go to the one that has
a value one step lower than the current pixel. Repeat until you have reached your
destination.
I knew I could easily convert this to the game dungeon by counting the rooms and passages
as the "object" and starting the count at the exit point. A few tricks would ensure
the implementation became simple. Thus, I auto-generated
an array identical in size to the dungeon map and filled it with two values: -1 for
walls or solid objects and 500 everywhere else. Then I located the exit/exits and gave
it/them the value 0. Finally, I set the distance-finding algorithm in motion, starting
from the 0. Negative values (i.e. -1) would count as being outside the free path.
The first room and its initial "distance map" are shown below.

-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 500 500 -1 500 500 500 500 -1 10 9 8 9 -1
-1 500 500 -1 500 500 500 500 -1 9 8 7 -1 -1
-1 500 500 -1 -1 -1 -1 -1 -1 10 -1 6 5 -1
-1 -1 -1 -1 14 13 14 13 12 11 -1 5 4 -1
-1 16 15 14 13 12 -1 -1 -1 -1 -1 4 3 -1
-1 -1 -1 -1 -1 11 -1 500 500 -1 -1 -1 2 -1
-1 500 500 500 -1 10 -1 -1 -1 -1 3 2 1 0
-1 500 500 500 -1 9 8 7 6 5 4 -1 2 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
Apparently, the closed prison cells have not been touched by the algorithm at all.
They still contain 500. But this is perfectly OK.
Whenever the player smashes something -- a door or another breakable object -- I
set the corresponding distance map value to its lowest positive neighboring value
plus one, and start the distance-finding algorithm anew from there.
All positive distance values that are higher than that of the current square,
plus one, are replaced and in turn put in a queue for later examination.
An added quality of the algorithm is that whenever it finds a block that has
an unchained prisoner standing on it, it replaces that part of the map with an
ordinary piece of ground and activates a prisoner, as a mobile character, on the
same spot.
In order to ensure that
the game runs smoothly, I only let the applet compute one distance level
per animation frame, but it will still only take a couple of seconds until the
entire room (where necessary) is affected. The changes spread very much like
rings on water. Sometimes it's possible to notice a split-second delay between
the moments prisoners at different distances from the door start cheering.
Below is a scene from later in the game with its corresponding distance map.

-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 500 500 -1 15 14 13 12 11 10 9 8 9 -1
-1 500 500 -1 16 15 14 13 -1 9 8 7 -1 -1
-1 500 500 -1 -1 -1 -1 -1 -1 10 -1 6 5 -1
-1 -1 -1 -1 14 13 14 13 12 11 -1 5 4 -1
-1 16 15 14 13 12 -1 -1 -1 -1 -1 4 3 -1
-1 -1 -1 -1 -1 11 -1 500 500 -1 -1 -1 2 -1
-1 14 13 12 -1 10 -1 -1 -1 -1 3 2 1 0
-1 13 12 11 10 9 8 7 6 5 4 -1 2 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
For practical purposes, I treat each room separately. It would take too much
unnecessary work to update the entire dungeon whenever the player breaks a crate
or something else. The "AI" still works perfectly within each room, though.
Whenever a prisoner reaches the value 0, I just let it keep going. That will send it
into the next room, where it can continue its path with the same exit-finding
strategy as before. (This may in fact be more realistic than if the prisoners
immediately knew the shortest path through the entire dungeon.)
|