Just a minor note. You'll need to change to something other than Manhattan distance as a heuristic if you want to guarantee the shortest path when you allow diagonal moves. Euclidean distance is the best you can do for grid worlds with uniform movement costs.

For "visitedMap", why not use boolean[][] rather than GridDouble's ArrayList<ArrayList<Double>>? You could also use a boolean[] and index it like array[y * width + x]. Even better, if you use int[][] then you can avoid calling reset(0). Instead you use an int "currentID". At the beginning of each path finding, you increment currentID. Then during path finding, if the int[x][y] != currentID you treat it as unset, else you treat it as set.

Just a minor note. You'll need to change to something other than Manhattan distance as a heuristic if you want to guarantee the shortest path when you allow diagonal moves. Euclidean distance is the best you can do for grid worlds with uniform movement costs.

I'm aware that Manhattan doesn't return necessarly the best path, but I failed to see why Euclidean would return the best one.

This pathfinding is suppose to find a ''good'' path even with non uniform movement cost in theory but I don't think it is the case with the current Heuristic.

For "visitedMap", why not use boolean[][] rather than GridDouble's ArrayList<ArrayList<Double>>? You could also use a boolean[] and index it like array[y * width + x]. Even better, if you use int[][] then you can avoid calling reset(0). Instead you use an int "currentID". At the beginning of each path finding, you increment currentID. Then during path finding, if the int[x][y] != currentID you treat it as unset, else you treat it as set.

Yeah I was lazy on that one... Do you think there is a big difference in speed between ArrayList<ArrayList<Double>> and double[][]?

Usually I prefer avoiding design that require currentID (what if currentID become greater than Integer.MAX_VALUE? ok stupid reason...)

I'm aware that Manhattan doesn't return necessarly the best path, but I failed to see why Euclidean would return the best one.

This pathfinding is suppose to find a ''good'' path even with non uniform movement cost in theory but I don't think it is the case with the current Heuristic.

To guarantee the shortest path the heuristic has to always be lower than the actual distance. So an ideal heuristic is one that is as high as possible but never quite goes over the actual distance to the goal.

For the grid-world the difference between Manhattan's estimate an the actual distance is worst when the goal is on a direct diagonal path from the current location. The Euclidean distance will be exactly the same as the real distance in this case, and will be lower than the actual distance in all other cases. Because the Euclidean distance gets estimates that are close to the real distance, the search will expand fewer nodes than a heuristic that gives lower values (e.g. a stupid heuristic that always guesses zero will still give the best path, but will expand lots more nodes).

What you might see with the Manhattan heuristic is that the search will try a diagonal move that will make a big jump in the heuristic, and then never have a chance to come back to try a horizontal or vertical move that is actually on a shorter path.

What you might see with the Manhattan heuristic is that the search will try a diagonal move that will make a big jump in the heuristic, and then never have a chance to come back to try a horizontal or vertical move that is actually on a shorter path.

Now I'm using an Heuristic that is always a bit bigger than the shortest path, won't it be slower if I use one that is always smaller?

Now I'm using an Heuristic that is always a bit bigger than the shortest path, won't it be slower if I use one that is always smaller?

Yep, it'll be slower but it will be guaranteed to find the shortest path. I had a play with the demo to find an example of what I was talking about:

The one on the left is what is returned by the Manhattan heuristic (current implementation). The one on the right is a shorter path that isn't found. Notice the early diagonal move that confuses the search on the left.

Now I'm using an Heuristic that is always a bit bigger than the shortest path, won't it be slower if I use one that is always smaller?

Yep, it'll be slower but it will be guaranteed to find the shortest path. I had a play with the demo to find an example of what I was talking about:

The one on the left is what is returned by the Manhattan heuristic (current implementation). The one on the right is a shorter path that isn't found. Notice the early diagonal move that confuses the search on the left.

If your heuristic is overestimating the distance then of course the pathfinding will not actually work. You've got to have an admissible heuristic.

For "visitedMap", why not use boolean[][] rather than GridDouble's ArrayList<ArrayList<Double>>? You could also use a boolean[] and index it like array[y * width + x]. Even better, if you use int[][] then you can avoid calling reset(0). Instead you use an int "currentID". At the beginning of each path finding, you increment currentID. Then during path finding, if the int[x][y] != currentID you treat it as unset, else you treat it as set.

This currentID method is ingenious, worked really well for me. No need to clear states all the time.

The problem is that you actually need to combine the results of the heuristic with the cost so far. So if just using the square of the heuristic you'd have f(x) = g(x) + h(x)*h(x), which for heuristic values greater than 1 would make the search tend to a best-first (and the heuristic is non-admissible).

Taking the square of the cost so far doesn't fix it either, because g(x)*g(x) + h(x)*h(x) still doesn't have the same metric properties as g(x) + h(x).

Yes, I should have clarified, I meant between Manhattan and Euclidean distances.

In my game Sinuosity because it's a maze where you can never go diagonally Manhattan distance works excellently. I would imagine that if you allowed diagonals you could just do a smarter version of Manhattan where you use sqrt(2) for the diagonals and 1 for direct angles. That is, if you consider a diagonal to cost more than u/d/l/r, considering it is in fact a longer distance.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org