1 //#define PATHLIB_RDFIELDS
\r
2 #ifdef PATHLIB_RDFIELDS
\r
3 #define path_next swampslug
\r
4 #define path_prev lasertarget
\r
14 .float pathlib_node_g;
\r
15 .float pathlib_node_h;
\r
16 .float pathlib_node_f;
\r
18 float pathlib_open_cnt;
\r
19 float pathlib_closed_cnt;
\r
20 float pathlib_made_cnt;
\r
21 float pathlib_merge_cnt;
\r
22 float pathlib_recycle_cnt;
\r
23 float pathlib_searched_cnt;
\r
25 float pathlib_bestopen_seached;
\r
26 float pathlib_bestcash_hits;
\r
27 float pathlib_bestcash_saved;
\r
29 float pathlib_gridsize;
\r
31 float pathlib_movecost;
\r
32 float pathlib_movecost_diag;
\r
33 float pathlib_movecost_waterfactor;
\r
35 float pathlib_edge_check_size;
\r
37 float pathlib_foundgoal;
\r
40 entity best_open_node;
\r
41 .float is_path_node;
\r
43 float edge_show(vector point,float fsize);
\r
45 //#define DEBUGPATHING
\r
47 void mark_error(vector where,float lifetime);
\r
48 void mark_info(vector where,float lifetime);
\r
49 entity mark_misc(vector where,float lifetime);
\r
53 void pathlib_showpath(entity start)
\r
59 te_lightning1(e,e.origin,e.path_next.origin);
\r
64 void path_dbg_think()
\r
66 pathlib_showpath(self);
\r
67 self.nextthink = time + 1;
\r
70 void __showpath2_think()
\r
72 mark_info(self.origin,1);
\r
75 self.path_next.think = __showpath2_think;
\r
76 self.path_next.nextthink = time + 0.15;
\r
80 self.owner.think = __showpath2_think;
\r
81 self.owner.nextthink = time + 0.15;
\r
85 void pathlib_showpath2(entity path)
\r
87 path.think = __showpath2_think;
\r
88 path.nextthink = time;
\r
94 float pathlib_stdproc_path_validate(vector start,vector end)
\r
96 tracebox(start, self.mins * 2, self.maxs * 2, end, MOVE_WORLDONLY, self);
\r
98 if(vlen(trace_endpos - end) < 5)
\r
106 void pathlib_deletepath(entity start)
\r
110 e = findchainentity(owner, start);
\r
113 e.think = SUB_Remove;
\r
114 e.nextthink = time;
\r
119 float fsnap(float val,float fsize)
\r
121 return rint(val / fsize) * fsize;
\r
124 vector vsnap(vector point,float fsize)
\r
128 vret_x = rint(point_x / fsize) * fsize;
\r
129 vret_y = rint(point_y / fsize) * fsize;
\r
130 vret_z = ceil(point_z / fsize) * fsize;
\r
136 #define floor_failmask (DPCONTENTS_SLIME | DPCONTENTS_LAVA)
\r
137 // | DPCONTENTS_MONSTERCLIP | DPCONTENTS_DONOTENTER
\r
138 float walknode_stepsize;
\r
139 vector walknode_stepup;
\r
140 vector walknode_maxdrop;
\r
141 vector walknode_boxup;
\r
142 vector walknode_boxmax;
\r
143 vector walknode_boxmin;
\r
144 float pathlib_movenode_goodnode;
\r
146 float floor_ok(vector point)
\r
150 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
\r
153 pc = pointcontents(point);
\r
157 case CONTENT_SOLID:
\r
158 case CONTENT_SLIME:
\r
162 case CONTENT_EMPTY:
\r
163 if not (pointcontents(point - '0 0 1') == CONTENT_SOLID)
\r
166 case CONTENT_WATER:
\r
169 if(pointcontents(point - '0 0 1') == CONTENT_SOLID)
\r
175 float inwater(vector point)
\r
177 if(pointcontents(point) == CONTENT_WATER)
\r
183 //#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if(trace_fraction == 1.0) return 1
\r
184 #define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if not(floor_ok(trace_endpos)) return 1
\r
185 float edge_check(vector point,float fsize)
\r
187 vector z_up,z_down;
\r
189 z_up = '0 0 1' * fsize;
\r
190 z_down = '0 0 1' * fsize;
\r
192 _pcheck(point + ('1 1 0' * fsize));
\r
193 _pcheck(point + ('1 -1 0' * fsize));
\r
194 _pcheck(point + ('1 0 0' * fsize));
\r
196 _pcheck(point + ('0 1 0' * fsize));
\r
197 _pcheck(point + ('0 -1 0' * fsize));
\r
199 _pcheck(point + ('-1 0 0' * fsize));
\r
200 _pcheck(point + ('-1 1 0' * fsize));
\r
201 _pcheck(point + ('-1 -1 0' * fsize));
\r
207 #define _pshow(p) mark_error(p,10)
\r
208 float edge_show(vector point,float fsize)
\r
211 _pshow(point + ('1 1 0' * fsize));
\r
212 _pshow(point + ('1 -1 0' * fsize));
\r
213 _pshow(point + ('1 0 0' * fsize));
\r
215 _pshow(point + ('0 1 0' * fsize));
\r
216 _pshow(point + ('0 -1 0' * fsize));
\r
218 _pshow(point + ('-1 0 0' * fsize));
\r
219 _pshow(point + ('-1 1 0' * fsize));
\r
220 _pshow(point + ('-1 -1 0' * fsize));
\r
226 var vector pathlib_movenode(vector start,vector end,float doedge);
\r
227 vector pathlib_wateroutnode(vector start,vector end)
\r
231 pathlib_movenode_goodnode = 0;
\r
233 end_x = fsnap(end_x, pathlib_gridsize);
\r
234 end_y = fsnap(end_y, pathlib_gridsize);
\r
236 traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
\r
237 end = trace_endpos;
\r
239 if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
\r
242 for(surface = start ; surface_z < (end_z + 32); ++surface_z)
\r
244 if(pointcontents(surface) == CONTENT_EMPTY)
\r
247 //mark_error(surface,10);
\r
249 if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
\r
252 tracebox(start + '0 0 64', walknode_boxmin,walknode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
\r
253 if(trace_fraction == 1)
\r
255 pathlib_movenode_goodnode = 1;
\r
256 //mark_error(end + '0 0 64',30);
\r
259 if(fabs(surface_z - end_z) > 32)
\r
260 pathlib_movenode_goodnode = 0;
\r
265 vector pathlib_swimnode(vector start,vector end)
\r
267 pathlib_movenode_goodnode = 0;
\r
269 if(pointcontents(start) != CONTENT_WATER)
\r
272 end_x = fsnap(end_x, pathlib_gridsize);
\r
273 end_y = fsnap(end_y, pathlib_gridsize);
\r
275 if(pointcontents(end) == CONTENT_EMPTY)
\r
276 return pathlib_wateroutnode( start, end);
\r
278 tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
\r
279 if(trace_fraction == 1)
\r
280 pathlib_movenode_goodnode = 1;
\r
285 vector pathlib_flynode(vector start,vector end)
\r
287 pathlib_movenode_goodnode = 0;
\r
290 if(pointcontents(start) == CONTENT_EMPTY)
\r
293 if(pointcontents(end) == CONTENT_EMPTY)
\r
296 end_x = fsnap(end_x, pathlib_gridsize);
\r
297 end_y = fsnap(end_y, pathlib_gridsize);
\r
299 tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
\r
300 if(trace_fraction == 1)
\r
301 pathlib_movenode_goodnode = 1;
\r
306 vector pathlib_walknode(vector start,vector end,float doedge)
\r
308 vector direction,point,last_point,s,e;
\r
309 float steps, distance, i,laststep;
\r
311 pathlib_movenode_goodnode = 0;
\r
317 direction = normalize(s - e);
\r
319 distance = vlen(start - end);
\r
320 laststep = distance / walknode_stepsize;
\r
321 steps = floor(laststep);
\r
322 laststep = laststep - steps;
\r
325 s = point + walknode_stepup;
\r
326 e = point - walknode_maxdrop;
\r
328 traceline(s, e,MOVE_WORLDONLY,self);
\r
329 if(trace_fraction == 1.0)
\r
330 return trace_endpos;
\r
332 if (floor_ok(trace_endpos) == 0)
\r
333 return trace_endpos;
\r
335 last_point = trace_endpos;
\r
337 for(i = 0; i < steps; ++i)
\r
339 point = last_point + direction * walknode_stepsize;
\r
341 s = point + walknode_stepup;
\r
342 e = point - walknode_maxdrop;
\r
343 traceline(s, e,MOVE_WORLDONLY,self);
\r
344 if(trace_fraction == 1.0)
\r
345 return trace_endpos;
\r
347 point = trace_endpos;
\r
348 if not(floor_ok(trace_endpos))
\r
349 return trace_endpos;
\r
351 tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
\r
352 if(trace_fraction != 1.0)
\r
353 return trace_endpos;
\r
356 if(edge_check(point,pathlib_edge_check_size))
\r
357 return trace_endpos;
\r
359 last_point = point;
\r
362 point = last_point + direction * walknode_stepsize * laststep;
\r
364 point_x = fsnap(point_x, pathlib_gridsize);
\r
365 point_y = fsnap(point_y, pathlib_gridsize);
\r
367 s = point + walknode_stepup;
\r
368 e = point - walknode_maxdrop;
\r
369 traceline(s, e,MOVE_WORLDONLY,self);
\r
371 if(trace_fraction == 1.0)
\r
372 return trace_endpos;
\r
374 point = trace_endpos;
\r
376 if not(floor_ok(trace_endpos))
\r
377 return trace_endpos;
\r
379 tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
\r
380 if(trace_fraction != 1.0)
\r
381 return trace_endpos;
\r
383 pathlib_movenode_goodnode = 1;
\r
387 var float pathlib_cost(entity parent,vector to, float static_cost);
\r
388 float pathlib_g_static(entity parent,vector to, float static_cost)
\r
391 return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
\r
393 return parent.pathlib_node_g + static_cost;
\r
396 float pathlib_g_euclidean(entity parent,vector to, float static_cost)
\r
398 return vlen(parent.origin - to);
\r
401 var float(vector from,vector to) pathlib_heuristic;
\r
402 float pathlib_h_manhattan(vector a,vector b)
\r
404 //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
\r
407 h = fabs(a_x - b_x);
\r
408 h = h + fabs(a_y - b_y);
\r
409 h = pathlib_gridsize * h;
\r
414 float pathlib_h_diagonal(vector a,vector b)
\r
416 //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
\r
419 x = fabs(a_x - b_x);
\r
420 y = fabs(a_y - b_y);
\r
421 h = pathlib_movecost * max(x,y);
\r
426 float pathlib_h_euclidean(vector a,vector b)
\r
428 return vlen(a - b);
\r
431 float pathlib_h_diagonal2(vector a,vector b)
\r
433 float h_diag,h_str,h,x,y;
\r
436 h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
\r
437 h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
\r
438 h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
\r
441 x = fabs(a_x - b_x);
\r
442 y = fabs(a_y - b_y);
\r
447 h = pathlib_movecost_diag * h_diag;
\r
448 h += pathlib_movecost * (h_str - 2 * h_diag);
\r
453 float pathlib_h_diagonal2tbs(vector start,vector point,vector end)
\r
455 float h_diag,h_str,h,x,y;
\r
458 h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
\r
459 h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
\r
460 h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
\r
463 float dx1,dx2,dy1,dy2,fcross;
\r
464 dx1 = point_x - end_x;
\r
465 dy1 = point_y - end_y;
\r
466 dx2 = start_x - end_x;
\r
467 dy2 = start_y - end_y;
\r
468 fcross = fabs(dx1*dy2 - dx2*dy1);
\r
470 x = fabs(point_x - end_x);
\r
471 y = fabs(point_y - end_y);
\r
476 h = pathlib_movecost_diag * h_diag;
\r
477 h += pathlib_movecost * (h_str - 2 * h_diag);
\r
479 return h + (fcross * 0.001);
\r
482 float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
\r
484 float h_diag,h_str,h,x,y,z;
\r
486 //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
\r
487 //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
\r
488 //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
\r
490 x = fabs(point_x - end_x);
\r
491 y = fabs(point_y - end_y);
\r
492 z = fabs(point_z - end_z);
\r
494 h_diag = min3(x,y,z);
\r
497 h = pathlib_movecost_diag * h_diag;
\r
498 h += pathlib_movecost * (h_str - 2 * h_diag);
\r
504 d1 = normalize(preprev - prev);
\r
505 d2 = normalize(prev - point);
\r
506 if(vlen(d1-d2) > 0.6)
\r
514 float pathlib_h_diagonal3(vector a,vector b)
\r
516 float h_diag,h_str,h,x,y,z;
\r
518 //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
\r
519 //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
\r
520 //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
\r
522 x = fabs(a_x - b_x);
\r
523 y = fabs(a_y - b_y);
\r
524 z = fabs(a_z - b_z);
\r
526 h_diag = min3(x,y,z);
\r
529 h = pathlib_movecost_diag * h_diag;
\r
530 h += pathlib_movecost * (h_str - 2 * h_diag);
\r
538 //#define PATHLIB_USE_NODESCRAP
\r
539 float pathlib_scraplist_cnt;
\r
543 #ifdef PATHLIB_USE_NODESCRAP
\r
544 if(pathlib_scraplist_cnt)
\r
546 n = findentity(world,owner,scraplist);
\r
549 --pathlib_scraplist_cnt;
\r
550 ++pathlib_recycle_cnt;
\r
554 pathlib_scraplist_cnt = 0;
\r
557 ++pathlib_made_cnt;
\r
562 void dumpnode(entity n)
\r
564 #ifdef PATHLIB_USE_NODESCRAP
\r
565 ++pathlib_scraplist_cnt;
\r
566 n.owner = scraplist;
\r
572 entity pathlib_mknode(vector where,entity parent)
\r
577 node.is_path_node = TRUE;
\r
578 node.owner = openlist;
\r
579 node.path_prev = parent;
\r
581 setorigin(node, where);
\r
583 ++pathlib_open_cnt;
\r
585 //if(inwater(where))
\r
587 //node.waterlevel = 1;
\r
588 //mark_info(where,5);
\r
590 //mark_info(where,30);
\r
593 var float pathlib_expandnode(entity node, vector start, vector goal);
\r
594 float pathlib_expandnode_star(entity node, vector start, vector goal);
\r
595 float pathlib_expandnode_box(entity node, vector start, vector goal);
\r
597 float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost)
\r
600 float h,g,f,doedge;
\r
603 ++pathlib_searched_cnt;
\r
605 if(inwater(parent.origin))
\r
609 //bprint("Switch to water tracing\n");
\r
610 pathlib_expandnode = pathlib_expandnode_box;
\r
611 pathlib_movenode = pathlib_swimnode;
\r
616 //bprint("Switch to get out of water tracing\n");
\r
617 pathlib_expandnode = pathlib_expandnode_box;
\r
618 pathlib_movenode = pathlib_swimnode;
\r
625 //bprint("Switch to get into water tracing\n");
\r
626 pathlib_expandnode = pathlib_expandnode_box;
\r
627 pathlib_movenode = pathlib_swimnode;
\r
632 //bprint("Switch to land tracing\n");
\r
633 pathlib_expandnode = pathlib_expandnode_star;
\r
634 pathlib_movenode = pathlib_walknode;
\r
639 where = pathlib_movenode(parent.origin,to,0);
\r
640 if not(pathlib_movenode_goodnode)
\r
642 //mark_error(where,15);
\r
647 if(edge_check(where,pathlib_edge_check_size))
\r
650 h = pathlib_heuristic(where,goal);
\r
653 if(parent.path_prev)
\r
654 h = pathlib_h_diagonal2sdp(parent.path_prev.origin,parent.origin,where,goal);
\r
656 h = pathlib_heuristic(where,goal);
\r
661 g = pathlib_cost(parent,where,cost);
\r
664 node = findradius(where,pathlib_gridsize * 0.75);
\r
667 if(node.is_path_node == TRUE)
\r
669 ++pathlib_merge_cnt;
\r
670 if(node.owner == openlist)
\r
672 if(node.pathlib_node_g > g)
\r
674 node.pathlib_node_h = h;
\r
675 node.pathlib_node_g = g;
\r
676 node.pathlib_node_f = f;
\r
677 node.path_prev = parent;
\r
680 if not (best_open_node)
\r
681 best_open_node = node;
\r
682 else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
\r
683 best_open_node = node;
\r
691 node = pathlib_mknode(where,parent);
\r
693 node.pathlib_node_h = h;
\r
694 node.pathlib_node_g = g;
\r
695 node.pathlib_node_f = f;
\r
697 if not (best_open_node)
\r
698 best_open_node = node;
\r
699 else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
\r
700 best_open_node = node;
\r
705 entity pathlib_getbestopen()
\r
712 ++pathlib_bestcash_hits;
\r
713 pathlib_bestcash_saved += pathlib_open_cnt;
\r
715 return best_open_node;
\r
718 node = findchainentity(owner,openlist);
\r
725 ++pathlib_bestopen_seached;
\r
726 if(node.pathlib_node_f < bestnode.pathlib_node_f)
\r
735 void pathlib_close_node(entity node,vector goal)
\r
738 if(node.owner == closedlist)
\r
740 dprint("Pathlib: Tried to close a closed node!\n");
\r
744 if(node == best_open_node)
\r
745 best_open_node = world;
\r
747 ++pathlib_closed_cnt;
\r
748 --pathlib_open_cnt;
\r
750 node.owner = closedlist;
\r
752 if(vlen(node.origin - goal) <= pathlib_gridsize)
\r
754 //if(vlen(node.origin - goal) < 128)
\r
756 goalmove = pathlib_walknode(node.origin,goal,1);
\r
757 if(pathlib_movenode_goodnode)
\r
760 pathlib_foundgoal = TRUE;
\r
765 float pathlib_expandnode_star(entity node, vector start, vector goal)
\r
771 where = node.origin;
\r
773 v_forward = '1 0 0';
\r
777 point = where + v_forward * pathlib_gridsize;
\r
778 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
\r
781 point = where - v_forward * pathlib_gridsize;
\r
782 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
\r
785 point = where + v_right * pathlib_gridsize;
\r
786 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
\r
789 point = where - v_right * pathlib_gridsize;
\r
790 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
\r
793 point = where + v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
\r
794 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
\r
797 point = where + v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
\r
798 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
\r
801 point = where - v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
\r
802 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
\r
805 point = where - v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
\r
806 nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
\r
808 return pathlib_open_cnt;
\r
811 float pathlib_expandnode_box(entity node, vector start, vector goal)
\r
815 for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
\r
816 for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
\r
817 for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
\r
819 if(vlen(v - node.origin))
\r
820 pathlib_makenode(node,start,v,goal,pathlib_movecost);
\r
823 return pathlib_open_cnt;
\r
826 void pathlib_cleanup()
\r
830 if(best_open_node != world)
\r
831 remove(best_open_node);
\r
833 best_open_node = world;
\r
835 node = findfloat(world,is_path_node, TRUE);
\r
838 node.path_next = world;
\r
839 node.path_prev = world;
\r
840 node.is_path_node = FALSE;
\r
843 node = findfloat(world,is_path_node, TRUE);
\r
850 remove(closedlist);
\r
853 entity pathlib_astar(vector from,vector to)
\r
860 pathlib_heuristic = pathlib_h_diagonal3;
\r
861 pathlib_cost = pathlib_g_static;
\r
862 pathlib_expandnode = pathlib_expandnode_star;
\r
863 pathlib_movenode = pathlib_walknode;
\r
866 openlist = spawn();
\r
869 closedlist = spawn();
\r
872 scraplist = spawn();
\r
874 pathlib_closed_cnt = 0;
\r
875 pathlib_open_cnt = 0;
\r
876 pathlib_made_cnt = 0;
\r
877 pathlib_merge_cnt = 0;
\r
878 pathlib_searched_cnt = 0;
\r
879 pathlib_bestcash_hits = 0;
\r
880 pathlib_bestcash_saved = 0;
\r
881 pathlib_recycle_cnt = 0;
\r
883 pathlib_gridsize = 192;
\r
884 pathlib_movecost = pathlib_gridsize;
\r
885 pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
\r
886 pathlib_movecost_waterfactor = 1.1;
\r
887 pathlib_foundgoal = 0;
\r
889 walknode_boxmax = self.maxs * 1.5;
\r
890 walknode_boxmin = self.mins * 1.5;
\r
892 pathlib_edge_check_size = (vlen(walknode_boxmin - walknode_boxmax) * 0.25);
\r
894 walknode_boxup = '0 0 2' * self.maxs_z;
\r
895 walknode_stepsize = 32;
\r
896 walknode_stepup = '0 0 1' * walknode_stepsize;
\r
897 walknode_maxdrop = '0 0 3' * walknode_stepsize;
\r
899 dprint("AStar init. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n");
\r
900 path = pathlib_mknode(from,world);
\r
901 pathlib_close_node(path,to);
\r
902 if(pathlib_foundgoal)
\r
904 dprint("A* Goal fond in first square!\n");
\r
908 open.classname = "path_end";
\r
909 setorigin(open,path.origin);
\r
915 if(pathlib_expandnode(path,from,to) <= 0)
\r
917 dprint("A* pathing fail\n");
\r
922 best_open_node = pathlib_getbestopen();
\r
923 n = best_open_node;
\r
924 pathlib_close_node(best_open_node,to);
\r
925 if(inwater(n.origin))
\r
926 pathlib_expandnode_box(n,from,to);
\r
928 pathlib_expandnode_star(n,from,to);
\r
930 //pathlib_expandnode(n,from,to);
\r
932 while(pathlib_open_cnt)
\r
934 best_open_node = pathlib_getbestopen();
\r
935 n = best_open_node;
\r
936 pathlib_close_node(best_open_node,to);
\r
938 if(inwater(n.origin))
\r
939 pathlib_expandnode_box(n,from,to);
\r
941 pathlib_expandnode(n,from,to);
\r
943 if(pathlib_foundgoal)
\r
945 dprint("Path found, re-tracing...\n");
\r
948 open.is_path_node = FALSE;
\r
949 open.classname = "path_end";
\r
951 open.path_next = world;
\r
954 while(open.path_prev != path)
\r
957 open = open.path_prev;
\r
959 open.path_next = n;
\r
961 open.is_path_node = FALSE;
\r
962 open.classname = "path_node";
\r
965 open.path_prev = path;
\r
966 path.path_next = open;
\r
967 path.classname = "path_master";
\r
968 path.is_path_node = FALSE;
\r
973 #ifdef DEBUGPATHING
\r
974 bprint("Chain done..\n");
\r
975 pathlib_showpath2(path);
\r
978 bprint(" Nodes reused: ", ftos(pathlib_recycle_cnt),"\n");
\r
979 bprint(" Nodes created: ", ftos(pathlib_made_cnt),"\n");
\r
980 bprint(" Nodes make/reuse: ", ftos(pathlib_made_cnt / pathlib_recycle_cnt),"\n");
\r
981 bprint(" Nodes open: ", ftos(pathlib_open_cnt),"\n");
\r
982 bprint(" Nodes merged: ", ftos(pathlib_merge_cnt),"\n");
\r
983 bprint(" Nodes closed: ", ftos(pathlib_closed_cnt),"\n");
\r
984 bprint(" Nodes searched: ", ftos(pathlib_searched_cnt),"\n");
\r
985 bprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
\r
986 bprint(" Nodes bestcash hits: ", ftos(pathlib_bestcash_hits),"\n");
\r
987 bprint(" Nodes bestcash save: ", ftos(pathlib_bestcash_saved),"\n");
\r
988 bprint("AStar done. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n\n");
\r
995 dprint("A* Faild to find a path! Try a smaller gridsize.\n");
\r