From efff1acc0b4000eb9f545360d71c44314c2cf8eb Mon Sep 17 00:00:00 2001 From: bagil Date: Tue, 11 Jul 2017 07:30:06 +0000 Subject: [PATCH] revert ff1198383a6497edc5967759be62bef6275d8f07 --- code/__HELPERS/AStar.dm | 841 +----------------- code/__HELPERS/_lists.dm | 1 - .../mob/living/simple_animal/bot/bot.dm | 4 +- 3 files changed, 21 insertions(+), 825 deletions(-) diff --git a/code/__HELPERS/AStar.dm b/code/__HELPERS/AStar.dm index d5db2ae73b8..45b27590013 100644 --- a/code/__HELPERS/AStar.dm +++ b/code/__HELPERS/AStar.dm @@ -29,722 +29,23 @@ Actual Adjacent procs : ////////////////////// //A* nodes variables -/datum/PathNode - var/turf/source //turf associated with the PathNode - var/astar_id //Id of the astar operation we belong to - var/datum/PathNode/parent //link to the parent PathNode - var/weight //f A* Node weight (f = g + h) - var/cost //g A* movement cost variable - var/heuristic //h A* heuristic variable = h - var/depth //ht count the number of Nodes traversed - var/datum/PathNode/next //next node in the linked stack. - -/datum/PathNode/New(s, id, p, pg, ph, pnt) - source = s - astar_id = id - parent = p - cost = pg - heuristic = ph - weight = pg + ph - depth = pnt - -/datum/PathNode/proc/calc_weight() - weight = cost + heuristic - - -////////////////////// -//A* procs -////////////////////// - -//reversed so that the Heap is a MinHeap rather than a MaxHeap -/proc/HeapPathWeightCompare(datum/PathNode/a, datum/PathNode/b) - return b.weight - a.weight - -//wrapper that returns an empty list if A* failed to find a path -/proc/get_path_to(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, list/exclude=null, simulated_only = 1) - . = AStar(caller, end, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only) - if (!.) - . = list() - -/proc/AStar(...) - var/static/const/num = 7 - var/static/cur = rand(0, num-1) - if (prob(33)) - cur = rand(0, num-1) - switch(cur) - if(0) - return AStar_linkedlist(arglist(args)) - if(1) - return AStar_linkedlist_oldclosed(arglist(args)) - if(2) - return AStar_linkedlist_manualrecalc(arglist(args)) - if(3) - return AStar_list(arglist(args)) - if(4) - return AStar_list_oldrecalc(arglist(args)) - if(5) - return AStar_associatedlist(arglist(args)) - if(6) - return AStar_turfvar(arglist(args)) - else - throw EXCEPTION("invalid chain state") - -//the actual algorithm -/proc/AStar_linkedlist(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++ - - //turfs we've looked at. - var/list/turfs = list() - //sanitation - var/start = get_turf(caller) - if(!start) - return 0 - if (!islist(exclude)) - if (exclude) - exclude = list(exclude) - else - exclude = list() - - - if(maxnodes) - //if start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return 0 - maxnodedepth = maxnodes //no need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list - var/list/path //the returned path, if any - var/list/closed = exclude - - //initialization - open.Insert(new /datum/PathNode(start, astar_id, null, 0, call(start ,dist)(end), 0)) - - - //then run the main loop - while(length(open.L) && !path) - //get the lower f node on the open list - var/datum/PathNode/cur = open.Pop() //current processed turf - closed += 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)) - break - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = list(cur.source) - while(cur.parent) - cur = cur.parent - path.Add(cur.source) - - break - - //get adjacent turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source, adjacent)(caller, id, simulated_only) - for(var/turf/T in L-closed) - var/datum/PathNode/P - var/newcost = cur.cost + call(cur.source, dist)(T) - - for(P = T.pathnodes; P && P.astar_id != astar_id; P = P.next); //byond magic - - if(!P) //new shit yall - var/datum/PathNode/newnode = new /datum/PathNode(T, astar_id, cur, newcost, call(T, dist)(end), cur.depth+1) - open.Insert(newnode) - //add ourselves to the top of the pathnodes linked stack (it was either this or make it a doublely linked list - //that would have added extra overhead to maintaining the linked list.) - newnode.next = T.pathnodes - T.pathnodes = newnode - turfs += T - - else //old shit, check if its still relevant - if(newcost < P.cost) - P.parent = cur - P.cost = (newcost * length(L) / 9) - P.calc_weight() - P.depth = cur.depth + 1 - open.ReSort(P)//reorder the changed element in the list - - - - //cleaning up after ourselves - for(var/thing in turfs) - var/turf/T = thing - var/datum/PathNode/head = T.pathnodes - if (head && head.astar_id == astar_id) - T.pathnodes = head.next - head.next = null - head.parent = null - head.source = null - 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 - next.next = null - next.parent = null - next.source = null - break - P = next - - - - //reverse the path to get it from start to finish - if (path) - for(var/i in 1 to path.len/2) - path.Swap(i,path.len-i+1) - - - return path - -/turf/var/datum/PathNode/pathnodes - -//the actual algorithm -/proc/AStar_linkedlist_oldclosed(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++ - - //turfs we've looked at. - var/list/turfs = list() - //sanitation - var/start = get_turf(caller) - if(!start) - return 0 - if (!islist(exclude)) - if (exclude) - exclude = list(exclude) - else - exclude = list() - - - if(maxnodes) - //if start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return 0 - maxnodedepth = maxnodes //no need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list - var/list/path //the returned path, if any - var/list/closed = exclude - - //initialization - open.Insert(new /datum/PathNode(start, astar_id, null, 0, call(start ,dist)(end), 0)) - - - //then run the main loop - while(length(open.L) && !path) - //get the lower f node on the open list - var/datum/PathNode/cur = open.Pop() //current processed turf - closed += 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)) - break - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = list(cur.source) - while(cur.parent) - cur = cur.parent - path.Add(cur.source) - - break - - //get adjacent turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source, adjacent)(caller, id, simulated_only) - for(var/turf/T in L) - if (T in closed) - continue - var/datum/PathNode/P - var/newcost = cur.cost + call(cur.source, dist)(T) - - for(P = T.pathnodes; P && P.astar_id != astar_id; P = P.next); //byond magic - - if(!P) //new shit yall - var/datum/PathNode/newnode = new /datum/PathNode(T, astar_id, cur, newcost, call(T, dist)(end), cur.depth+1) - open.Insert(newnode) - //add ourselves to the top of the pathnodes linked stack (it was either this or make it a doublely linked list - //that would have added extra overhead to maintaining the linked list.) - newnode.next = T.pathnodes - T.pathnodes = newnode - turfs += T - - else //old shit, check if its still relevant - if(newcost < P.cost) - P.parent = cur - P.cost = (newcost * length(L) / 9) - P.calc_weight() - P.depth = cur.depth + 1 - open.ReSort(P)//reorder the changed element in the list - - - - //cleaning up after ourselves - for(var/thing in turfs) - var/turf/T = thing - var/datum/PathNode/head = T.pathnodes - if (head && head.astar_id == astar_id) - T.pathnodes = head.next - head.next = null - head.parent = null - head.source = null - 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 - next.next = null - next.parent = null - next.source = null - break - P = next - - - - //reverse the path to get it from start to finish - if (path) - for(var/i in 1 to path.len/2) - path.Swap(i,path.len-i+1) - - - return path - - -/proc/AStar_linkedlist_manualrecalc(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++ - - //turfs we've looked at. - var/list/turfs = list() - //sanitation - var/start = get_turf(caller) - if(!start) - return 0 - if (!islist(exclude)) - if (exclude) - exclude = list(exclude) - else - exclude = list() - - - if(maxnodes) - //if start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return 0 - maxnodedepth = maxnodes //no need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list - var/list/path //the returned path, if any - var/list/closed = exclude - - //initialization - open.Insert(new /datum/PathNode(start, astar_id, null, 0, call(start ,dist)(end), 0)) - - - //then run the main loop - while(length(open.L) && !path) - //get the lower f node on the open list - var/datum/PathNode/cur = open.Pop() //current processed turf - closed += 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)) - break - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = list(cur.source) - while(cur.parent) - cur = cur.parent - path.Add(cur.source) - - break - - //get adjacent turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source, adjacent)(caller, id, simulated_only) - for(var/turf/T in L-closed) - var/datum/PathNode/P - var/newcost = cur.cost + call(cur.source, dist)(T) - - for(P = T.pathnodes; P && P.astar_id != astar_id; P = P.next); //byond magic - - if(!P) //new shit yall - var/datum/PathNode/newnode = new /datum/PathNode(T, astar_id, cur, newcost, call(T, dist)(end), cur.depth+1) - open.Insert(newnode) - //add ourselves to the top of the pathnodes linked stack (it was either this or make it a doublely linked list - //that would have added extra overhead to maintaining the linked list.) - newnode.next = T.pathnodes - T.pathnodes = newnode - turfs += T - - else //old shit, check if its still relevant - if(newcost < P.cost) - 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 - - - - //cleaning up after ourselves - for(var/thing in turfs) - var/turf/T = thing - var/datum/PathNode/head = T.pathnodes - if (head && head.astar_id == astar_id) - T.pathnodes = head.next - head.next = null - head.parent = null - head.source = null - 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 - next.next = null - next.parent = null - next.source = null - break - P = next - - - - //reverse the path to get it from start to finish - if (path) - for(var/i in 1 to path.len/2) - path.Swap(i,path.len-i+1) - - - return path - - - - -//A* nodes variables -/datum/PathNode2 - var/turf/source //turf associated with the PathNode - var/astar_id //Id of the astar operation we belong to - var/datum/PathNode2/parent //link to the parent PathNode - var/weight //f A* Node weight (f = g + h) - var/cost //g A* movement cost variable - var/heuristic //h A* heuristic variable = h - var/depth //ht count the number of Nodes traversed - var/closed = FALSE - -/datum/PathNode2/New(s, id, p, pg, ph, pnt) - source = s - astar_id = id - parent = p - cost = pg - heuristic = ph - weight = pg + ph - depth = pnt - -/datum/PathNode2/proc/calc_weight() - weight = cost + heuristic - - -////////////////////// -//A* procs -////////////////////// - -//reversed so that the Heap is a MinHeap rather than a MaxHeap -/proc/HeapPathWeightCompare2(datum/PathNode2/a, datum/PathNode2/b) - return b.weight - a.weight - - -//the actual algorithm -/proc/AStar_list(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++ - - //turfs we've looked at. - var/list/turfs = list() - //sanitation - var/start = get_turf(caller) - if(!start) - return 0 - if (!islist(exclude)) - if (exclude) - exclude = list(exclude) - else - exclude = list() - - //make it assoicated - for (var/T in exclude) - exclude[T] = 1 - - if(maxnodes) - //if start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return 0 - maxnodedepth = maxnodes //no need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare2) //the open list - var/list/path = null //the returned path, if any - var/datum/PathNode2/cur //current processed turf - - //initialization - open.Insert(new /datum/PathNode2(start, astar_id, null, 0, call(start ,dist)(end), 0)) - - //then run the main loop - while(length(open.L) && !path) - //get the lower f node on the open list - cur = open.Pop() //get the lower f turf in the open list - cur.closed = TRUE //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)) - continue - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = new() - path.Add(cur.source) - - while(cur.parent) - cur = cur.parent - path.Add(cur.source) - - break - - //get adjacents turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source,adjacent)(caller, id, simulated_only) - for(var/turf/T in L) - if(exclude[T]) - continue - - - - //99% of the time, the first node will be ours, so we can skip a for overhead by lazy accessing. - var/datum/PathNode2/P = LAZYACCESSFAST(T.pathnodes2, 1) - - if (!P || P.astar_id != astar_id) - P = null - for (var/thing in T.pathnodes2) - var/datum/PathNode2/PN = thing - if (PN.astar_id == astar_id) - P = PN - break - if(!P) - //is not already in open list, so add it - var/newcost = cur.cost + call(cur.source,dist)(T) - var/datum/PathNode2/newnode = new /datum/PathNode2(T, astar_id, cur, newcost, call(T, dist)(end), cur.depth+1) - open.Insert(newnode) - LAZYADD(T.pathnodes2, newnode) - turfs += T - - else //is already in open list, check if it's a better way from the current turf - if (P.closed) - continue - var/newcost = cur.cost + call(cur.source,dist)(T) - if(newcost < P.cost) - 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 - - - //cleaning up after us - for(var/thing in turfs) - var/turf/T = thing - - var/datum/PathNode2/P = LAZYACCESSFAST(T.pathnodes2, 1) - - if (!P || P.astar_id != astar_id) - for (var/thing2 in T.pathnodes2) - var/datum/PathNode2/PN = thing2 - if (PN.astar_id == astar_id) - P = PN - break - - T.pathnodes2 -= P - UNSETEMPTY(T.pathnodes2) - - - - //reverse the path to get it from start to finish - if(path) - for(var/i in 1 to path.len/2) - path.Swap(i,path.len-i+1) - - return path - -//the actual algorithm -/proc/AStar_list_oldrecalc(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++ - - //turfs we've looked at. - var/list/turfs = list() - //sanitation - var/start = get_turf(caller) - if(!start) - return 0 - if (!islist(exclude)) - if (exclude) - exclude = list(exclude) - else - exclude = list() - - //make it assoicated - for (var/T in exclude) - exclude[T] = 1 - - if(maxnodes) - //if start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return 0 - maxnodedepth = maxnodes //no need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare2) //the open list - var/list/path = null //the returned path, if any - var/datum/PathNode2/cur //current processed turf - - //initialization - open.Insert(new /datum/PathNode2(start, astar_id, null, 0, call(start ,dist)(end), 0)) - - //then run the main loop - while(length(open.L) && !path) - //get the lower f node on the open list - cur = open.Pop() //get the lower f turf in the open list - cur.closed = TRUE //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)) - continue - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = new() - path.Add(cur.source) - - while(cur.parent) - cur = cur.parent - path.Add(cur.source) - - break - - //get adjacents turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source,adjacent)(caller, id, simulated_only) - for(var/turf/T in L) - if(exclude[T]) - continue - - - - //99% of the time, the first node will be ours, so we can skip a for overhead by lazy accessing. - var/datum/PathNode2/P = LAZYACCESSFAST(T.pathnodes2, 1) - - if (!P || P.astar_id != astar_id) - P = null - for (var/thing in T.pathnodes2) - var/datum/PathNode2/PN = thing - if (PN.astar_id == astar_id) - P = PN - break - if(!P) - //is not already in open list, so add it - var/newcost = cur.cost + call(cur.source,dist)(T) - var/datum/PathNode2/newnode = new /datum/PathNode2(T, astar_id, cur, newcost, call(T, dist)(end), cur.depth+1) - open.Insert(newnode) - LAZYADD(T.pathnodes2, newnode) - turfs += T - - else //is already in open list, check if it's a better way from the current turf - if (P.closed) - continue - var/newcost = cur.cost + call(cur.source,dist)(T) - if(newcost < P.cost) - P.parent = cur - P.cost = (newcost * length(L) / 9) - P.calc_weight() - P.depth = cur.depth + 1 - open.ReSort(P)//reorder the changed element in the list - - - //cleaning up after us - for(var/thing in turfs) - var/turf/T = thing - - var/datum/PathNode2/P = LAZYACCESSFAST(T.pathnodes2, 1) - - if (!P || P.astar_id != astar_id) - for (var/thing2 in T.pathnodes2) - var/datum/PathNode2/PN = thing2 - if (PN.astar_id == astar_id) - P = PN - break - - T.pathnodes2 -= P - UNSETEMPTY(T.pathnodes2) - - - - //reverse the path to get it from start to finish - if(path) - for(var/i in 1 to path.len/2) - path.Swap(i,path.len-i+1) - - return path - - -/turf/var/list/pathnodes2 - - - -////////////////////// -//PathNode object -////////////////////// - -//A* nodes variables -/PathNode3 +/PathNode var/turf/source //turf associated with the PathNode - var/PathNode3/prevNode //link to the parent PathNode + var/PathNode/prevNode //link to the parent PathNode var/f //A* Node weight (f = g + h) var/g //A* movement cost variable var/h //A* heuristic variable var/nt //count the number of Nodes traversed -/PathNode3/New(s,p,pg,ph,pnt) +/PathNode/New(s,p,pg,ph,pnt) source = s prevNode = p g = pg h = ph f = g + h - source.PNode3 = src nt = pnt -/PathNode3/proc/calc_f() +/PathNode/proc/calc_f() f = g + h ////////////////////// @@ -752,124 +53,22 @@ Actual Adjacent procs : ////////////////////// //the weighting function, used in the A* algorithm -///proc/PathWeightCompare2(PathNode/a, PathNode/b) -// return a.f - b.f +/proc/PathWeightCompare(PathNode/a, PathNode/b) + return a.f - b.f //reversed so that the Heap is a MinHeap rather than a MaxHeap -/proc/HeapPathWeightCompare3(PathNode3/a, PathNode3/b) +/proc/HeapPathWeightCompare(PathNode/a, PathNode/b) return b.f - a.f -//the actual algorithm -/proc/AStar_turfvar(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) - //sanitation - var/start = get_turf(caller) - if(!start) - return 0 - - if(maxnodes) - //if start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return 0 - maxnodedepth = maxnodes //no need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare3) //the open list - var/list/closed = new() //the closed list - var/list/path = null //the returned path, if any - var/PathNode3/cur //current processed turf - - //initialization - open.Insert(new /PathNode3(start,null,0,call(start,dist)(end),0)) - - //then run the main loop - while(!open.IsEmpty() && !path) - //get the lower f node on the open list - cur = open.Pop() //get the lower f turf in the open list - closed.Add(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.nt > maxnodedepth)) - continue - - //found the target turf (or close enough), let's create the path to it - if(cur.source == end || closeenough) - path = new() - path.Add(cur.source) - - while(cur.prevNode) - cur = cur.prevNode - path.Add(cur.source) - - break - - //get adjacents turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source,adjacent)(caller,id, simulated_only) - for(var/turf/T in L) - if(T == exclude || (T in closed)) - continue - - var/newg = cur.g + call(cur.source,dist)(T) - if(!T.PNode3) //is not already in open list, so add it - open.Insert(new /PathNode3(T,cur,newg,call(T,dist)(end),cur.nt+1)) - else //is already in open list, check if it's a better way from the current turf - if(newg < T.PNode3.g) - T.PNode3.prevNode = cur - T.PNode3.g = (newg * L.len / 9) - T.PNode3.calc_f() - T.PNode3.nt = cur.nt + 1 - open.ReSort(T.PNode3)//reorder the changed element in the list - - - //cleaning after us - for(var/PathNode3/PN in open.L) - PN.source.PNode3 = null - for(var/turf/T in closed) - T.PNode3 = null - - //reverse the path to get it from start to finish - if(path) - for(var/i = 1; i <= path.len/2; i++) - path.Swap(i,path.len-i+1) - +//wrapper that returns an empty list if A* failed to find a path +/proc/get_path_to(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) + var/list/path = AStar(caller, end, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only) + if(!path) + path = list() return path - -/turf/var/PathNode3/PNode3 - -////////////////////// -//PathNode object -////////////////////// - -//A* nodes variables -/PathNode4 - var/turf/source //turf associated with the PathNode - var/PathNode4/prevNode //link to the parent PathNode - var/f //A* Node weight (f = g + h) - var/g //A* movement cost variable - var/h //A* heuristic variable - var/nt //count the number of Nodes traversed - -/PathNode4/New(s,p,pg,ph,pnt) - source = s - prevNode = p - g = pg - h = ph - f = g + h - nt = pnt - -/PathNode4/proc/calc_f() - f = g + h - -//reversed so that the Heap is a MinHeap rather than a MaxHeap -/proc/HeapPathWeightCompare4(PathNode4/a, PathNode4/b) - return b.f - a.f - //the actual algorithm -/proc/AStar_associatedlist(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) +/proc/AStar(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) var/list/pnodelist = list() //sanitation var/start = get_turf(caller) @@ -882,13 +81,13 @@ Actual Adjacent procs : return 0 maxnodedepth = maxnodes //no need to consider path longer than maxnodes - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare4) //the open list + var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) //the open list var/list/closed = new() //the closed list var/list/path = null //the returned path, if any - var/PathNode4/cur //current processed turf + var/PathNode/cur //current processed turf //initialization - open.Insert(new /PathNode4(start,null,0,call(start,dist)(end),0)) + open.Insert(new /PathNode(start,null,0,call(start,dist)(end),0)) //then run the main loop while(!open.IsEmpty() && !path) @@ -924,10 +123,10 @@ Actual Adjacent procs : var/newg = cur.g + call(cur.source,dist)(T) - var/PathNode4/P = pnodelist[T] + var/PathNode/P = pnodelist[T] if(!P) //is not already in open list, so add it - var/PathNode4/newnode = new /PathNode4(T,cur,newg,call(T,dist)(end),cur.nt+1) + var/PathNode/newnode = new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1) open.Insert(newnode) pnodelist[T] = newnode else //is already in open list, check if it's a better way from the current turf @@ -937,6 +136,7 @@ Actual Adjacent procs : P.calc_f() P.nt = cur.nt + 1 open.ReSort(P)//reorder the changed element in the list + CHECK_TICK //cleaning after us @@ -949,7 +149,6 @@ Actual Adjacent procs : return path - //Returns adjacent turfs in cardinal directions that are reachable //simulated_only controls whether only simulated turfs are considered or not /turf/proc/reachableAdjacentTurfs(caller, ID, simulated_only) @@ -958,7 +157,7 @@ Actual Adjacent procs : for(var/dir in GLOB.cardinals) T = get_step(src,dir) - if(!T || (simulated_only && istype(T, /turf/open/space))) + if(simulated_only && !istype(T)) continue if(!T.density && !LinkBlockedWithAccess(T,caller, ID)) L.Add(T) diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 4566a7e97ae..d63c10c508d 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -456,7 +456,6 @@ #define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } } #define LAZYADD(L, I) if(!L) { L = list(); } L += I; #define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null) -#define LAZYACCESSFAST(L, I) (L ? L[I] : null) #define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V; #define LAZYLEN(L) length(L) #define LAZYCLEARLIST(L) if(L) L.Cut() diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index bba91f05b8a..d5526cac999 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -116,9 +116,7 @@ update_icon() /mob/living/simple_animal/bot/Initialize() - speed += rand(-1,1) ..() - base_speed += rand(-1,1) access_card = new /obj/item/weapon/card/id(src) //This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first. access_card.access += GLOB.access_robotics @@ -435,7 +433,7 @@ Pass a positive integer as an argument to override a bot's default speed. path = list() return 0 var/step_count = move_speed ? move_speed : base_speed //If a value is passed into move_speed, use that instead of the default speed var. - step_count += rand(0, 2) + if(step_count >= 1 && tries < BOT_STEP_MAX_RETRIES) for(var/step_number = 0, step_number < step_count,step_number++) spawn(BOT_STEP_DELAY*step_number)