Best response
That's one way to optimize a standard A*.

I think, however, what Doohl is struggling with is more specifically in the how to, and not necessarily in optimization.


Doohl: This is a common problem. Your brain is stuck in the grid. Forget the grid for a minute. A grid is just a network of nodes in two-dimensional space.

BYOND's tile-based pathing assumes that nodes are tiles on a grid. So a square having 8 neighbors is completely arbitrary. You are already determining links with your dotted lines. Use those to determine your neighbors.

In your case, you are forgoing locality for the sake of explicitly declared links.

Thus, you can forget about investigating any unusual algorithm, and use A* just like normal for tile-based pathing:

proc
Astar(var/node/startnode,var/node/endnode)
var/list/checked = list() //keep track of where we've been already
var/list/checking = list() //where we still need to check
var/list/lastnode = list() //keep track of how we got to each node
var/list/path //used for the final return

var/node/cur //the currently being checked node

checking += startnode //seed the list with our start value
checked[startnode] = 1

while(checking.len) //keep checking as long as we have places to go
cur = checking[1]
checking -= cur

if(cur==endnode)
//reconstruct the path
path = list()
while(cur!=startnode)
path.Insert(1,cur)
cur = lastnode[cur]
return path

for(var/node/n in cur.links) //check all neighbors
if(!checked[n]) //if it's a fresh link
checking += n
checked[n] = 1
lastnode[n] = cur
//pathfinding failed
return null


This is hum-drum A*, with no optimizations, and no heuristic. Any node is as good as any other for searching. You can improves this by hunting the shortest nodes first, or by hunting the node in the closest direction first. Whatever you decide.
And a wave of similar algorithms appears.
You guys make me feel like some sort of peasant code monkey. :(
In response to Ter13
Well, I just noticed that mine returns the path in reverse order, so you get my vote :P
Thanks, everyone, you've helped tremendously! I even learned something today ;)
Did I help? :(
In response to Jittai
You got some thought churning at least.
In response to Jittai
Jittai wrote:
Did I help? :(

Lol, Your suggestions were actually incredibly useful for later optimization. Apply your heuristic to my code, and it'll function a lot faster in the majority of cases.
Oh, and when you have time:

http://harablog.wordpress.com/2011/09/07/jump-point-search/

The jump point search is good for equal-cost pathfinding solutions, but that's about it. It won't help you with variable cost at all.
In response to Ter13
That's some nice code. A* never really crossed my mind when thinking about this, but I guess there's a lot of similarity.

Ter13 wrote:
        //pathfinding failed
return null


Why do that? It's redundant. The . var will already return null anyway, by default. The failure will make no difference in this case. Redundant code is a habit that I try to stay away from, unless of course I'm feeling extra paranoid at the time!
Notation in this case, but like I've said before, it's a habit from languages where you don't have a VM to babysit you.

If you don't have a return path in C++, your compiler is going to throw a fit. --It's a micro-optimization in this case, but yeah, I agree. It's a point that gets pointed out a lot to me.

In the case of what I try to put on the forums, though, I'd prefer to be extra careful than put out tightly packed, needlessly optimized code.
Page: 1 2