|
@@ -39,6 +39,9 @@ struct path_node {
|
|
|
|
|
|
/// Binary heap of path nodes
|
|
|
BHEAP_STRUCT_DECL(node_heap, struct path_node*);
|
|
|
+static BHEAP_STRUCT_VAR(node_heap, g_open_set); // use static heap for all path calculations
|
|
|
+ // it get's initialized in do_init_path, freed in do_final_path.
|
|
|
+
|
|
|
|
|
|
/// Comparator for binary heap of path nodes (minimum cost at top)
|
|
|
#define NODE_MINTOPCMP(i,j) ((i)->f_cost - (j)->f_cost)
|
|
@@ -58,6 +61,16 @@ static const unsigned char walk_choices [3][3] =
|
|
|
{DIR_SOUTHWEST,DIR_SOUTH,DIR_SOUTHEAST},
|
|
|
};
|
|
|
|
|
|
+
|
|
|
+void do_init_path(){
|
|
|
+ BHEAP_INIT(g_open_set); // [fwi]: BHEAP_STRUCT_VAR already initialized the heap, this is rudendant & just for code-conformance/readability
|
|
|
+}//
|
|
|
+
|
|
|
+void do_final_path(){
|
|
|
+ BHEAP_CLEAR(g_open_set);
|
|
|
+}//
|
|
|
+
|
|
|
+
|
|
|
/*==========================================
|
|
|
* Find the closest reachable cell, 'count' cells away from (x0,y0) in direction (dx,dy).
|
|
|
* Income after the coordinates of the blow
|
|
@@ -249,6 +262,8 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16
|
|
|
* flag: &1 = easy path search only
|
|
|
* flag: &2 = call path_search_long instead
|
|
|
* cell: type of obstruction to check for
|
|
|
+ *
|
|
|
+ * Note: uses global g_open_set, therefore this method can't be called in parallel or recursivly.
|
|
|
*------------------------------------------*/
|
|
|
bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
|
|
|
{
|
|
@@ -313,8 +328,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
|
|
// A* (A-star) pathfinding
|
|
|
// We always use A* for finding walkpaths because it is what game client uses.
|
|
|
// Easy pathfinding cuts corners of non-walkable cells, but client always walks around it.
|
|
|
-
|
|
|
- BHEAP_STRUCT_VAR(node_heap, open_set); // 'Open' set
|
|
|
+ BHEAP_RESET(g_open_set);
|
|
|
|
|
|
// FIXME: This array is too small to ensure all paths shorter than MAX_WALKPATH
|
|
|
// can be found without node collision: calc_index(node1) = calc_index(node2).
|
|
@@ -337,7 +351,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
|
|
tp[i].f_cost = heuristic(x0, y0, x1, y1);
|
|
|
tp[i].flag = SET_OPEN;
|
|
|
|
|
|
- heap_push_node(&open_set, &tp[i]); // Put start node to 'open' set
|
|
|
+ heap_push_node(&g_open_set, &tp[i]); // Put start node to 'open' set
|
|
|
|
|
|
for(;;) {
|
|
|
int e = 0; // error flag
|
|
@@ -352,13 +366,12 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
|
|
|
|
|
int g_cost;
|
|
|
|
|
|
- if (BHEAP_LENGTH(open_set) == 0) {
|
|
|
- BHEAP_CLEAR(open_set);
|
|
|
+ if (BHEAP_LENGTH(g_open_set) == 0) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- current = BHEAP_PEEK(open_set); // Look for the lowest f_cost node in the 'open' set
|
|
|
- BHEAP_POP2(open_set, NODE_MINTOPCMP, swap_ptr); // Remove it from 'open' set
|
|
|
+ current = BHEAP_PEEK(g_open_set); // Look for the lowest f_cost node in the 'open' set
|
|
|
+ BHEAP_POP2(g_open_set, NODE_MINTOPCMP, swap_ptr); // Remove it from 'open' set
|
|
|
|
|
|
x = current->x;
|
|
|
y = current->y;
|
|
@@ -367,7 +380,6 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
|
|
current->flag = SET_CLOSED; // Add current node to 'closed' set
|
|
|
|
|
|
if (x == x1 && y == y1) {
|
|
|
- BHEAP_CLEAR(open_set);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -379,24 +391,23 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
|
|
|
#define chk_dir(d) ((allowed_dirs & (d)) == (d))
|
|
|
// Process neighbors of current node
|
|
|
if (chk_dir(PATH_DIR_SOUTH|PATH_DIR_EAST) && !map_getcellp(md, x+1, y-1, cell))
|
|
|
- e += add_path(&open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5
|
|
|
+ e += add_path(&g_open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5
|
|
|
if (chk_dir(PATH_DIR_EAST))
|
|
|
- e += add_path(&open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6
|
|
|
+ e += add_path(&g_open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6
|
|
|
if (chk_dir(PATH_DIR_NORTH|PATH_DIR_EAST) && !map_getcellp(md, x+1, y+1, cell))
|
|
|
- e += add_path(&open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7
|
|
|
+ e += add_path(&g_open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7
|
|
|
if (chk_dir(PATH_DIR_NORTH))
|
|
|
- e += add_path(&open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0
|
|
|
+ e += add_path(&g_open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0
|
|
|
if (chk_dir(PATH_DIR_NORTH|PATH_DIR_WEST) && !map_getcellp(md, x-1, y+1, cell))
|
|
|
- e += add_path(&open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1
|
|
|
+ e += add_path(&g_open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1
|
|
|
if (chk_dir(PATH_DIR_WEST))
|
|
|
- e += add_path(&open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2
|
|
|
+ e += add_path(&g_open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2
|
|
|
if (chk_dir(PATH_DIR_SOUTH|PATH_DIR_WEST) && !map_getcellp(md, x-1, y-1, cell))
|
|
|
- e += add_path(&open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3
|
|
|
+ e += add_path(&g_open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3
|
|
|
if (chk_dir(PATH_DIR_SOUTH))
|
|
|
- e += add_path(&open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4
|
|
|
+ e += add_path(&g_open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4
|
|
|
#undef chk_dir
|
|
|
if (e) {
|
|
|
- BHEAP_CLEAR(open_set);
|
|
|
return false;
|
|
|
}
|
|
|
}
|