I would really like to see dwarves choose crafting materials, dump sites, water sources, etc based on path distance instead of straight-line distance. I think that dwarves choosing the garbage dump on the surface 20 levels up - through twisty turny passages - over the garbage dump at the magma pool 21 tiles to the side of them, with a clear path to it and all, qualifies as a bug.
I've been thinking about this, and I wonder if there's an algorithm to check for it that has an average-case performance not that much worse than the current one but will still work. Just speculating on an algorithm, so someone check my thought here.
OK, so, you begin by calculating the linear distance to each object and sorting them - the exact current procedure. Then you use the following principle: Any object to which the linear distance from the current point is X will have a pathing distance to that object greater than X.
So you check the closest object, call it Object A, by linear distance, and calculate a path to that, let's call the length of that path path(A) and the linear distance to that object dist(A).
Then you go down the ordered list of objects skipping over any objects that are in exactly the same place as A (because there's no point trying them - we'll pick A instead) until we find an object not in the same place as A, we'll call that Object B. We compare path(A) to dist(B), which we know already. If path(A) <= dist(B), we know for sure that A is the closest object by walking, since path(B) >= dist(B) and dist(everything else) > dist(B).
Alternatively, if the path to A is longer than the crow-flies distance to B, then we have to calculate path(B) and test whether it's shorter than path(A). If not, we go to the next object in the list that isn't in the same place as B, object C, and check if path(A) <= dist(C). If path(B) is shorter than path(A), we switch to that and then compare it to C.
This continues until we find reach object for which the linear distance to that object is GREATER than the shortest path distance we've calculated so far. At each object in the ordered list we've had to do one or two simple calculations - are they in the same position, then is their linear distance greater than the current shortest pathing distance. We've also had to calculate a bunch of routes.
However, and here's the bit that I think might be a bit of a breakthrough - you really won't have to calculate that many paths in the vast, vast majority of cases, probably just a few. It will, at minimum, require the calculation of one path for each currently linear-distance using function. My sense is that that won't be a *huge* slowdown, the problem is having to calculate loads of paths, which should be very rare. Most of the time it will check paths to a few linearly close objects and find one for which the linear path and the actual path are very close, and then quickly stop.
The worst case scenario would be a workshop vertically adjacent to a stockpile with hundreds of usable objects in it, but no direct access to any of them. They're all going to be very close, so paths will be calculated for all of them (and all those paths will be very long) before the iterating pathing/distance function reaches an object with a shorter path - one on the same Z-level as the workshop, let's say - and then quickly stops soon after because it's found a very direct path. That could create loads of slowdown. But that sort of thing should only happen due to bad layout design on behalf of the player, the average runtime of this algorithm should be much better than that.
Am I off base here? The way I see it, either this is a great idea (yay!), or there's an error in my algorithm, or the cost of calculating one or two paths for each job is so high that even this optimised solution would be too slow.