/* 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; }
static void visit_coords(map_t *m,int startX, int startY, int x, int y, int dx, int dy, TCOD_list_t active_views, bool light_walls) { // top left int tlx=x, tly=y+STEP_SIZE; // bottom right int brx=x+STEP_SIZE, bry=y; view_t *view=NULL; while (current_view != (view_t **)TCOD_list_end(active_views)) { view=*current_view; if ( ! BELOW_OR_COLINEAR(&view->steep_line,brx,bry) ) { break; } current_view++; } if ( current_view == (view_t **)TCOD_list_end(active_views) || ABOVE_OR_COLINEAR(&view->shallow_line,tlx,tly)) { // no more active view return; } if ( !is_blocked(m,view,startX,startY,x,y,dx,dy,light_walls) ) return; if ( ABOVE(&view->shallow_line,brx,bry) && BELOW(&view->steep_line,tlx,tly)) { // view blocked // slow ! TCOD_list_remove_iterator(active_views,(void **)current_view); } else if ( ABOVE(&view->shallow_line,brx,bry)) { // shallow bump add_shallow_bump(tlx,tly,view); check_view(active_views,current_view); } else if (BELOW(&view->steep_line,tlx,tly)) { // steep bump add_steep_bump(brx,bry,view); check_view(active_views,current_view); } else { // view splitted int offset=startX+x*dx/STEP_SIZE + (startY+y*dy/STEP_SIZE)*m->width; view_t *shallower_view= & views[offset]; int view_index=current_view - (view_t **)TCOD_list_begin(active_views); view_t **shallower_view_it; view_t **steeper_view_it; *shallower_view=**current_view; // slow ! shallower_view_it = (view_t **)TCOD_list_insert_before(active_views,shallower_view,view_index); steeper_view_it=shallower_view_it+1; current_view=shallower_view_it; add_steep_bump(brx,bry,shallower_view); if (!check_view(active_views,shallower_view_it)) steeper_view_it--; add_shallow_bump(tlx,tly,*steeper_view_it); check_view(active_views,steeper_view_it); if ( view_index > TCOD_list_size(active_views)) current_view=(view_t **)TCOD_list_end(active_views); } }
/* run the parser */ void namegen_parser_run (const char * filename) { char ** it; /* prepare the parser --- this will be executed only once */ namegen_parser_prepare(); if (parsed_files == NULL) parsed_files = TCOD_list_new(); if (TCOD_list_size(parsed_files) > 0) { for (it = (char **)TCOD_list_begin(parsed_files); it != (char **)TCOD_list_end(parsed_files); it++) if (strcmp(*it,filename) == 0) return; } /* if the file hasn't been parsed yet, add its name to the list so that it's never parsed twice */ TCOD_list_push(parsed_files,(const void *)TCOD_strdup(filename)); /* run the parser */ TCOD_parser_run(namegen_parser,filename,&namegen_listener); }
/* check whether a given generator already exists */ bool namegen_generator_check (const char * name) { /* if the list is not created yet, create it */ if (namegen_generators_list == NULL) { namegen_generators_list = TCOD_list_new(); return false; } /* otherwise, scan it for the name */ else { namegen_t ** it; for (it = (namegen_t**)TCOD_list_begin(namegen_generators_list); it < (namegen_t**)TCOD_list_end(namegen_generators_list); it++) { if (strcmp((*it)->name,name) == 0) return true; } return false; } }
/* this is the slow part, when we change the heuristic of a cell already in the heap */ static void heap_reorder(TCOD_path_data_t *path, uint32 offset) { uintptr *array=(uintptr *)TCOD_list_begin(path->heap); uintptr *end=(uintptr *)TCOD_list_end(path->heap); uintptr *cur=array; /* find the node corresponding to offset ... SLOW !! */ while (cur != end) { if (*cur == offset ) break; cur++; } if ( cur == end ) return; /* remove it... SLOW !! */ TCOD_list_remove_iterator(path->heap,(void **)cur); /* put it back on the heap */ TCOD_list_push(path->heap,(void *)(uintptr)offset); /* bubble the value up to its real position */ heap_sift_up(path,path->heap); }
/* search for occurrences of illegal strings */ bool namegen_word_has_illegal (namegen_t * data, char * str) { /* convert word to lowercase */ char * haystack = TCOD_strdup(str); int i; for(i = 0; i < (int)strlen(haystack); i++) haystack[i] = (char)(tolower(haystack[i])); /* look for illegal strings */ if (TCOD_list_size(data->illegal_strings) > 0) { char ** it; for (it = (char**)TCOD_list_begin(data->illegal_strings); it != (char**)TCOD_list_end(data->illegal_strings); it++) { if (strstr(haystack,*it) != NULL) { free(haystack); return true; } } } free(haystack); return false; }
static void heap_sift_up(TCOD_path_data_t *path, TCOD_list_t heap) { /* sift-up : move the last element of the heap up to its right place */ int end = TCOD_list_size(heap)-1; int child=end; uintptr *array=(uintptr *)TCOD_list_begin(heap); while ( child > 0 ) { uintptr off_child=array[child]; float child_dist=path->heur[off_child]; int parent = (child-1)/2; uintptr off_parent=array[parent]; float parent_dist=path->heur[off_parent]; if ( parent_dist > child_dist ) { /* get up one level */ uintptr tmp = array[child]; array[child]=array[parent]; array[parent]=tmp; child=parent; } else return; } }
static void render_log(struct engine *engine, int start_x, int start_y) { /* draw the message log */ double color_coef = 0.4f; int y = start_y; TCOD_list_t log = engine->gui->log; struct message **iter; for (iter = (struct message **) TCOD_list_begin(log); iter != (struct message **) TCOD_list_end(log); iter++) { struct message *message = *iter; // TCOD_color_t col = TCOD_color_multiply_scalar(message->col, color_coef); TCOD_console_set_default_foreground(engine->gui->con, message->col); TCOD_console_print(engine->gui->con, start_x, y, message->text); y++; if (color_coef < 1.0f) color_coef += 0.3f; } }
/* small layer on top of TCOD_list_t to implement a binary heap (min_heap) */ static void heap_sift_down(TCOD_path_data_t *path, TCOD_list_t heap) { /* sift-down : move the first element of the heap down to its right place */ int cur=0; int end = TCOD_list_size(heap)-1; int child=1; uintptr *array=(uintptr *)TCOD_list_begin(heap); while ( child <= end ) { int toSwap=cur; uint32 off_cur=array[cur]; float cur_dist=path->heur[off_cur]; float swapValue=cur_dist; uint32 off_child=array[child]; float child_dist=path->heur[off_child]; if ( child_dist < cur_dist ) { toSwap=child; swapValue=child_dist; } if ( child < end ) { /* get the min between child and child+1 */ uintptr off_child2=array[child+1]; float child2_dist=path->heur[off_child2]; if ( swapValue > child2_dist ) { toSwap=child+1; swapValue=child2_dist; } } if ( toSwap != cur ) { /* get down one level */ uintptr tmp = array[toSwap]; array[toSwap]=array[cur]; array[cur]=tmp; cur=toSwap; } else return; child=cur*2+1; } }
void TCOD_list_add_all(TCOD_list_t l, TCOD_list_t l2) { void **curElt; for ( curElt = TCOD_list_begin(l2); curElt != TCOD_list_end(l2); curElt ++) { TCOD_list_push(l,*curElt); } }
/* this is the slow part, when we change the heuristic of a cell already in the heap */ static void heap_reorder(TCOD_path_data_t *path, uint32 offset) { uintptr *array=(uintptr *)TCOD_list_begin(path->heap); uintptr *end=(uintptr *)TCOD_list_end(path->heap); uintptr *cur=array; uintptr off_idx=0; float value; int idx=0; int heap_size=TCOD_list_size(path->heap); /* find the node corresponding to offset ... SLOW !! */ while (cur != end) { if (*cur == offset ) break; cur++;idx++; } if ( cur == end ) return; off_idx=array[idx]; value=path->heur[off_idx]; if ( idx > 0 ) { int parent=(idx-1)/2; /* compare to its parent */ uintptr off_parent=array[parent]; float parent_value=path->heur[off_parent]; if (value < parent_value) { /* smaller. bubble it up */ while ( idx > 0 && value < parent_value ) { /* swap with parent */ array[parent]=off_idx; array[idx] = off_parent; idx=parent; if ( idx > 0 ) { parent=(idx-1)/2; off_parent=array[parent]; parent_value=path->heur[off_parent]; } } return; } } /* compare to its sons */ while ( idx*2+1 < heap_size ) { int child=idx*2+1; uintptr off_child=array[child]; int toSwap=idx; int child2; float swapValue=value; if ( path->heur[off_child] < value ) { /* swap with son1 ? */ toSwap=child; swapValue=path->heur[off_child]; } child2 = child+1; if ( child2 < heap_size ) { uintptr off_child2=array[child2]; if ( path->heur[off_child2] < swapValue) { /* swap with son2 */ toSwap=child2; } } if ( toSwap != idx ) { /* bigger. bubble it down */ uintptr tmp = array[toSwap]; array[toSwap]=array[idx]; array[idx] = tmp; idx=toSwap; } else return; } }