Skip to content
Margen67 edited this page Apr 22, 2021 · 3 revisions

Peep pathfinding ai is mostly handled by the function peep_pathfind_choose_direction.

Peep pathfind choose direction

The function takes as arguments the coordinates of the current location and the peep. The goal location is set as a global var.

Initially it resets the following vars to the following values:

0x00F1AED8 = 50,000 (staff), 15,000 (guests)
(number of junctions to check) 0x00F1AEDC = 16 (staff), 16 - 10 (guests [depends on other things])

Next if the target location is the current peeps target it will use the peep pathfind history (4 path find locations) to simplify the searching edges.

If the current location is not a path or is blocked on all sides the function will return unsuccessful (-1).

It next tries every available edge to path find to the location. This is done by iterating the edges and using function sub_69A997 to assess a score for how good a pathfind it is. Before calling 69a997 the following variables are set:

0x00F1AED3 = 255
0x00F1AED4 = 0x00F1AED8 (see above)
0x00F1AEDE = 0

Sub 69A997

This function takes an initial coordinate, score, edge and number of tiles and returns a score. When calling this function it iterates multiple times to get the final score the parameters score and num_tiles (counter) should be set to -1 and 0.

Location is incremented in the current direction.

Every time 69A997 is called 0x00F1AED4 is decremented this variable prevents stack overflows by only allowing a certain number of tiles to be looked at in total. If 0x00F1AED4 gets to 0 then it will return the current score.

Much like 0x00F1AED4 counter represents the number of tiles from the first call that 69a997 has got to. A distance greater than 200 tiles will always force the score to be returned.

|   |   |   |   |
-----------------
|   | x |   | G |
-----------------
| 2 | 1 | 2 |   |

In the above if every tile is pathable then the start location x has 4 initial directions. So 69A997 would be called 4 times. The first time is represented as 1. When at location 1 it can go in two directions (ignoring backwards) these are represented as 2. 0x00F1AED4 would be decremented twice to check these two locations but counter would only be decremented once.

The next part of the function assess the current pathfinding score. This is taken as the difference between the current location and the pathfinding goal. The smaller of the x or y difference is divided by 16 and difference in z is multiplied by 2. This is then all added together to create the score. z is very important to be correct so that is why it has a multiplier (i expect). The lower the score the better the pathfind. 0 means the location has been found. If the score is zero the function can return successfully. Whenever the score improves it is saved. The current number of steps is also saved at the same time in 0x00F1AED3. If the score is the same but takes less steps (counter) then the new number is saved.

|   |   |   |   |
-----------------
|   | x |   | G |
-----------------
| 2 | 1 | 2 |   |

In the first call of the above at location 1 the score is ( 2 + 1 / 16) = 2. This is currently the best score after 1 move.

The peep now has two options at the locations "2". The score for the left most one will be (3 + 1 / 16) = 3, and the right most one will be (1 + 1 / 16) = 1. The right most one has the better score.

The next part of the function assess if the location is possible. To be possible the location must have a path. If it does not have a path then it will return the current score (the branch has ended). If the path is sloped and it does not connect with the current location then this is not possible. If the path is wide (>3x3 tiles) then the location is not possible this is to prevent meandering on wide paths. If it is a queue path and we are not looking for this queue path then it is not possible (note mechanics override this check to allow walking up queues).

|   |   |   |   |
-----------------
|   | x |   | G |
-----------------
| 2 | 1 | 2 |   |

After getting to location 1 a check in the down direction would be unsuccessful as it has no valid path this direction would return the score of location 1.

Now that a new path location has been found the permitted edges of the new tile are looked at. If there are no permitted edges then this path is not possible and the score is returned. (Backwards is not a permitted edge)

If there is only 1 edge possible then there is no need to do any more checks as this is the only direction. 0x00F1AEDE is incremented and sub_69A997 is called again but for our new location and direction.

| - | x | - | 4 | 5 | G |
-------------------------
| - | 1 | 2 | 3 | - |   |

In the above example - represents an invalid tile. As there is only one direction at each location (backwards is not permitted) the goal can be reached without any issues. Note this means a <200 length path with no junctions is very easily pathed even if it meanders.

If 0x00F1AEDE is none zero such as after a one direction string of path then 0x00F1AEDC is decremented twice. Otherwise it is decremented once. If 0x00F1AEDC is less than zero then score is returned (this route is too long).

0x00F1AEDC represents the number of junction walked, long sections of no choice tiles are ignored (This incidentally is the reason why mechanics can often end up choosing a very long route instead of a direct route with more choices. #3423)

The function then iterates each of the valid edges and calls sub_69A997 on each of them. 0x00F1AEDE is reset to zero to prevent no choice routes affecting future tiles. 0x00F1AEDC is saved and then restored at each call as it represents the current routes number of tiles and needs to start the same for each direction. The score is saved after each call so that it can be checked each time to see if it's better.

Clone this wiki locally