anchor.diff:  			return AStar_goof(arglist(args))
   		else
   			throw EXCEPTION("invalid chain state")
  -*/
  +
   //the actual algorithm
  -/proc/AStar(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, list/exclude=null, simulated_only = 1)
  +/proc/AStar_new(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, list/exclude=null, simulated_only = 1)
   	var/static/next_astar_id = 1
   	var/astar_id = next_astar_id++
   
  
positive.code: 
  	//then run the main loop
  	while(length(open.L) && !path)
  		path = AStar_whileloop(open, turfs, maxnodes, dist, end, mintargetdist, maxnodedepth, closed, adjacent, id, astar_id, simulated_only, caller)
  
  		CHECK_TICK
  
  	AStar_cleanup(turfs, astar_id)
  
  
  
  	//reverse the path to get it from start to finish
  	if (path)
  		AStar_reverse(path)
  
  	return path
  
  /proc/AStar_reverse(list/path)
  	for(var/i in 1 to  path.len/2)
  		path.Swap(i,path.len-i+1)
  
  
  /proc/AStar_cleanup(list/turfs, astar_id)
  	//cleaning up after us
  	for(var/thing in turfs)
  		var/turf/T = thing
  		var/datum/PathNode/head = T.pathnodes
  		if (head.astar_id == astar_id)
  			T.pathnodes = head.next
  			continue
  		var/datum/PathNode/P = head
  		while (P)
  			var/datum/PathNode/next = P.next
  			if (next && next.astar_id == astar_id)
  				P.next = next.next
  				break
  			P = next
  
  
  
  
  /proc/AStar_whileloop(Heap/open, list/turfs, maxnodes, dist, turf/end, mintargetdist, maxnodedepth, list/exclude, adjacent, id, astar_id, simulated_only, caller)
  	//get the lower f node on the open list
  	var/datum/PathNode/cur = open.Pop() //current processed turf
  	exclude += cur.source //and tell we've processed it
  
  	//if we only want to get near the target, check if we're close enough
  	var/closeenough
  	if(mintargetdist)
  		closeenough = call(cur.source, dist)(end) <= mintargetdist
  
  	//if too many steps, abandon that path
  	if(maxnodedepth && (cur.depth > maxnodedepth))
  		return
  
  	//found the target turf (or close enough), let's create the path to it
  	if(cur.source == end || closeenough)
  		var/list/path = list(cur.source)
  
  		while(cur.parent)
  			cur = cur.parent
  			path.Add(cur.source)
  
  		return path
  
  	//get adjacent turfs using the adjacent proc, checking for access with id
  	var/list/L = call(cur.source, adjacent)(caller, id, simulated_only)
  	AStar_filter_turfs(L, cur, open, turfs, astar_id, dist, end, exclude)
  
  /proc/AStar_filter_turfs(list/L, datum/PathNode/cur, Heap/open, list/turfs, astar_id, dist, end, list/exclude)
  	for(var/turf/T in L-exclude)
  
  		var/datum/PathNode/P = AStar_find_pathnode(T, astar_id)
  		if(!P)
  			AStar_make_new_pathnode(cur, dist, T, turfs, astar_id, end, open)
  
  		else //is already in open list, check if it's a better way from the current turf
  			AStar_check_existing_pathnode(cur, P, dist, L, T, open)
  
  /proc/AStar_check_existing_pathnode(datum/PathNode/cur, datum/PathNode/P, dist, list/L, turf/T, Heap/open)
  	var/newcost = cur.cost + call(cur.source, dist)(T)
  	if(newcost < P.cost)
  		AStar_recalc_existing_pathnode(cur, newcost, P, L, open)
  
  /proc/AStar_recalc_existing_pathnode(datum/PathNode/cur, newcost, datum/PathNode/P, list/L, Heap/open)
  	P.parent = cur
  	P.cost = (newcost * length(L) / 9)
  	P.weight = P.cost + P.heuristic
  	P.depth = cur.depth + 1
  	open.ReSort(P)//reorder the changed element in the list
  
  /proc/AStar_make_new_pathnode(datum/PathNode/cur, dist, turf/T, turfs, astar_id, end, Heap/open)
  	var/newcost = cur.cost + call(cur.source, dist)(T)
  	var/datum/PathNode/newnode = new /datum/PathNode(T, astar_id, cur, newcost, call(T, dist)(end), cur.depth+1)
  	open.Insert(newnode)
  	newnode.next = T.pathnodes
  	T.pathnodes = newnode
  	turfs += T
  
  /proc/AStar_find_pathnode(turf/T, astar_id)
  	//99% of the time, the first node will be ours, so we can skip a for overhead by lazy accessing.
  	var/datum/PathNode/P = AStar_find_pathnode_quick_try(T)
  
  	if (!P || P.astar_id != astar_id)
  		return AStar_find_pathnode_full_try(P, astar_id)
  
  	return P
  
  /proc/AStar_find_pathnode_full_try(datum/PathNode/P, astar_id)
  	var/datum/PathNode/PN
  	for(PN = P; PN && PN.astar_id != astar_id; PN = PN.next); //byond magic
  	return PN
  
  /proc/AStar_find_pathnode_quick_try(turf/T)
  	return T.pathnodes
  
  
  /turf/var/list/pathnodes
  
negative.code: 		else
  			exclude = list()
  
  
  	if(maxnodes)
  		//if start turf is farther than maxnodes from end turf, no need to do anything
  