amethyst / bracket-lib

The Roguelike Toolkit (RLTK), implemented for Rust.
MIT License
1.52k stars 108 forks source link

Feature request: Implement A* JPS (Jump Point Search) #150

Open BezPowell opened 4 years ago

BezPowell commented 4 years ago

I'm never sure how much preamble to put into feature requests, but first of all would like to say thank you so much for creating such a useful library and set of tutorials. I've found both absolutely invaluable in learning to programme games and improving my Rust skills in general, it would have been a much harder slog without.

Onto the feature request: I'm using the A algorithm for real-time path finding and overall it works really well, however in a similar situation to issue #134, where a the direct route to a target is blocked, but a circuitous route does exist the performance can drop dramatically trying to figure out alternative routes. JPS looks like a substantial optimisation on A that can help in situations such as these as well as providing a general performance boost.

As it is an algorithm specifically designed to optimise path-finding over homogeneous grids it would likely be a great benefit to the development of games in general and in particular rougelikes.

My Rust skills and general knowledge of path-finding are definitely in their infancy, but I would certainly be happy to try and take a crack at this at a later date if others might find it useful / nobody more knowledgeable than myself beats me to it.

BezPowell commented 4 years ago

Despite saying I'd look at this at a later date I've actually been having a bit of a play around with trying to implement this. There's still a lot more work to do (I'm not currently using any of the bracket-lib crates, just trying to get a minimal implementation working), but the initial results are looking very promising (at least compared to the implementation of A* I made to figure out how it works).

Still a lot of re-factoring needed, but hopefully in a few weeks I might have something PR worthy if you feel it would make a good addition to the library?

I'm currently using the movingai-rust crate and the data from https://www.movingai.com/benchmarks/ for benchmarking. So far the most promising result has been the below:

Benchmark 68
A* (240, 142) -> (252, 164)     in 184 seconds and 702.201712 ms
Reached in optimal distance: 26.970562, 23 steps
JPS (240, 142) -> (252, 164)    in 0 seconds and 0.028664 ms
Reached in optimal distance: 26.970562, 4 steps

This is very obviously cherry picking from a synthetic benchmark, but hopefully it may translate into improved performance in certain real-world situations.

BezPowell commented 4 years ago

I now have what seems to be a fully working implementation of a JPS algorithm. I've uploaded the source code to github here: https://github.com/BezPowell/blitz-path if people want to take a look at it. I would very much like to try and convert this into a form where it would work with bracket-lib, but perhaps some discussion would be needed on whether this is desired and how to go about doing it if so?

As it shares a lot of similarity with the A* algorithm it might make sense for them to share certain underlying structures such as the Node and NavigationPath structs, but I'm not sure how best to organise that file hierachy wise: I don't want to go treading on anyone else's toes or doing things in a way which would make adding additional algorithms more difficult in the future if it was decided to do so.

I'd welcome any feedback anyone has on this.