/* walk the path */ bool TCOD_dijkstra_path_walk (TCOD_dijkstra_t dijkstra, int *x, int *y) { dijkstra_t * data = (dijkstra_t*)dijkstra; TCOD_IFNOT(data != NULL) return false; if (TCOD_list_is_empty(data->path)) return false; else { unsigned int node = (unsigned int)(uintptr)TCOD_list_pop(data->path); if ( x ) *x = (int)(node % data->width); if ( y ) *y = (int)(node / data->width); } return true; }
/* get the coordinate pair with the minimum A* score from the heap */ static uint32 heap_get(TCOD_path_data_t *path,TCOD_list_t heap) { /* return the first value of the heap (minimum score) */ uintptr *array=(uintptr *)TCOD_list_begin(heap); int end=TCOD_list_size(heap)-1; uint32 off=(uint32)(array[0]); /* take the last element and put it at first position (heap root) */ array[0] = array[end]; TCOD_list_pop(heap); /* and bubble it down to its real position */ heap_sift_down(path,heap); return off; }
/* create a path */ bool TCOD_dijkstra_path_set (TCOD_dijkstra_t dijkstra, int x, int y) { dijkstra_t * data = (dijkstra_t*)dijkstra; int px = x, py = y; static int dx[9] = { -1, 0, 1, 0, -1, 1, 1, -1, 0 }; static int dy[9] = { 0, -1, 0, 1, -1, -1, 1, 1, 0 }; unsigned int distances[9]; int lowest_index = 666; TCOD_IFNOT(data != NULL) return false; TCOD_IFNOT((unsigned)x < (unsigned)data->width && (unsigned)y < (unsigned)data->height) return false; // check that destination is reachable if ( dijkstra_get_int_distance(data,x,y) == 0xFFFFFFFF ) return false; TCOD_list_clear(data->path); do { unsigned int lowest = 0xFFFFFFFF; int i; TCOD_list_push(data->path,(const void*)(uintptr)((py * data->width) + px)); for(i=0;i<8;i++) { int cx = px + dx[i]; int cy = py + dy[i]; if ((unsigned)cx < (unsigned)data->width && (unsigned)cy < (unsigned)data->height) distances[i] = dijkstra_get_int_distance(data,cx,cy); else distances[i] = 0xFFFFFFFF; } distances[8] = dijkstra_get_int_distance(data,px,py); for(i=0;i<9;i++) if (distances[i] < lowest) { lowest = distances[i]; lowest_index = i; } px += dx[lowest_index]; py += dy[lowest_index]; } while (lowest_index != 8); // remove the last step TCOD_list_pop(data->path); return true; }
bool TCOD_bsp_traverse_inverted_level_order(TCOD_bsp_t *node, TCOD_bsp_callback_t listener, void *userData) { TCOD_list_t stack1=TCOD_list_new(); TCOD_list_t stack2=TCOD_list_new(); TCOD_list_push(stack1,node); while ( ! TCOD_list_is_empty(stack1) ) { TCOD_bsp_t *node=(TCOD_bsp_t *)TCOD_list_get(stack1,0); TCOD_list_push(stack2,node); TCOD_list_remove(stack1,node); if ( TCOD_bsp_left(node) ) TCOD_list_push(stack1,TCOD_bsp_left(node)); if ( TCOD_bsp_right(node) ) TCOD_list_push(stack1,TCOD_bsp_right(node)); } while ( ! TCOD_list_is_empty(stack2) ) { TCOD_bsp_t *node=(TCOD_bsp_t *)TCOD_list_pop(stack2); if (!listener(node,userData)) { TCOD_list_delete(stack1); TCOD_list_delete(stack2); return false; } } TCOD_list_delete(stack1); TCOD_list_delete(stack2); return true; }
bool TCOD_path_walk(TCOD_path_t p, int *x, int *y, bool recalculate_when_needed) { int newx,newy; float can_walk; int d; TCOD_path_data_t *path=(TCOD_path_data_t *)p; TCOD_IFNOT(p != NULL) return false; if ( TCOD_path_is_empty(path) ) return false; d=(int)(uintptr)TCOD_list_pop(path->path); newx=path->ox + dirx[d]; newy=path->oy + diry[d]; /* check if the path is still valid */ can_walk = TCOD_path_walk_cost(path,path->ox,path->oy,newx,newy); if ( can_walk == 0.0f ) { if (! recalculate_when_needed ) return false; /* don't walk */ /* calculate a new path */ if (! TCOD_path_compute(path, path->ox,path->oy, path->dx,path->dy) ) return false ; /* cannot find a new path */ return TCOD_path_walk(p,x,y,true); /* walk along the new path */ } if ( x ) *x=newx; if ( y ) *y=newy; path->ox=newx; path->oy=newy; return true; }