static void create_corridor(heap_t *h, path_node_c_t *path_arr) { path_node_c_t *curr_p, *curr_n_p; while(h->size > 0) { curr_p = (path_node_c_t *) heap_remove_min(h); curr_p->heap_node = NULL; curr_n_p = path_arr + (MAP_WIDTH * (curr_p->y - 1)) + curr_p->x; if(curr_n_p->heap_node != NULL) { if(curr_n_p->distance > curr_p->distance + curr_n_p->weight) { curr_n_p->distance = curr_p->distance + curr_n_p->weight; curr_n_p->previous = curr_p; heap_decrease_key_no_replace(h, curr_n_p->heap_node); } } curr_n_p = path_arr + (MAP_WIDTH * curr_p->y) + curr_p->x + 1; if(curr_n_p->heap_node != NULL) { if(curr_n_p->distance > curr_p->distance + curr_n_p->weight) { curr_n_p->distance = curr_p->distance + curr_n_p->weight; curr_n_p->previous = curr_p; heap_decrease_key_no_replace(h, curr_n_p->heap_node); } } curr_n_p = path_arr + (MAP_WIDTH * (curr_p->y + 1)) + curr_p->x; if(curr_n_p->heap_node != NULL) { if(curr_n_p->distance > curr_p->distance + curr_n_p->weight) { curr_n_p->distance = curr_p->distance + curr_n_p->weight; curr_n_p->previous = curr_p; heap_decrease_key_no_replace(h, curr_n_p->heap_node); } } curr_n_p = path_arr + (MAP_WIDTH * curr_p->y) + curr_p->x - 1; if(curr_n_p->heap_node != NULL) { if(curr_n_p->distance > curr_p->distance + curr_n_p->weight) { curr_n_p->distance = curr_p->distance + curr_n_p->weight; curr_n_p->previous = curr_p; heap_decrease_key_no_replace(h, curr_n_p->heap_node); } } } }
static void connect_rooms(cell_t *cell_arr, room_t *room_arr, int num_room) { int i, x, y; path_node_c_t *path_arr, *curr_p; heap_t *h; room_t *room; h = (heap_t *) malloc(sizeof(*h)); for(i = 1; i < num_room; i++) { room = room_arr + i; x = random_number(room->x, room->x + room->width - 1); y = random_number(room->y, room->y + room->height - 1); heap_init(h, gen_path_node_cmp, NULL); path_arr = (path_node_c_t *) malloc(MAP_HEIGHT * MAP_WIDTH * sizeof(*path_arr)); initialize_heap(h, path_arr, cell_arr); curr_p = path_arr + (MAP_WIDTH * y) + x; curr_p->weight = 1; curr_p->distance = 0; curr_p->previous = NULL; heap_decrease_key_no_replace(h, curr_p->heap_node); create_corridor(h, path_arr); room = room_arr + i - 1; x = random_number(room->x, room->x + room->width - 1); y = random_number(room->y, room->y + room->height - 1); curr_p = path_arr + (MAP_WIDTH * y) + x; place_corridor(curr_p, cell_arr); heap_delete(h); free(path_arr); } free(h); }
void dijkstra(dungeon_t *d) { /* Currently assumes that monsters only move on floors. Will * * need to be modified for tunneling and pass-wall monsters. */ heap_t h; uint32_t x, y; static path_t p[DUNGEON_Y][DUNGEON_X], *c; static uint32_t initialized = 0; if (!initialized) { initialized = 1; dungeon = d; for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { p[y][x].pos[dim_y] = y; p[y][x].pos[dim_x] = x; } } } for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { d->pc_distance[y][x] = 255; } } d->pc_distance[d->pc.position[dim_y]][d->pc.position[dim_x]] = 0; heap_init(&h, dist_cmp, NULL); for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { if (mapxy(x, y) >= ter_floor) { p[y][x].hn = heap_insert(&h, &p[y][x]); } } } while ((c = heap_remove_min(&h))) { c->hn = NULL; if ((p[c->pos[dim_y] - 1][c->pos[dim_x] - 1].hn) && (d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] - 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] - 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] - 1][c->pos[dim_x] ].hn) && (d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] ] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] ] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] ].hn); } if ((p[c->pos[dim_y] - 1][c->pos[dim_x] + 1].hn) && (d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] + 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] - 1][c->pos[dim_x] + 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] + 1].hn); } if ((p[c->pos[dim_y] ][c->pos[dim_x] - 1].hn) && (d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] - 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] - 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] ][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] ][c->pos[dim_x] + 1].hn) && (d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] + 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] ][c->pos[dim_x] + 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] ][c->pos[dim_x] + 1].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] - 1].hn) && (d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] - 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] - 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] ].hn) && (d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] ] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] ] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] ].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] + 1].hn) && (d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] + 1] > d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1)) { d->pc_distance[c->pos[dim_y] + 1][c->pos[dim_x] + 1] = d->pc_distance[c->pos[dim_y]][c->pos[dim_x]] + 1; heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] + 1].hn); } } heap_delete(&h); }
/* This is the same basic algorithm as in move.c, but * * subtle differences make it difficult to reuse. */ static void dijkstra_corridor(dungeon_t *d, pair_t from, pair_t to) { static corridor_path_t path[DUNGEON_Y][DUNGEON_X], *p; static uint32_t initialized = 0; heap_t h; uint32_t x, y; if (!initialized) { for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { path[y][x].pos[dim_y] = y; path[y][x].pos[dim_x] = x; } } initialized = 1; } for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { path[y][x].cost = INT_MAX; } } path[from[dim_y]][from[dim_x]].cost = 0; heap_init(&h, corridor_path_cmp, NULL); for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { if (mapxy(x, y) != ter_wall_immutable) { path[y][x].hn = heap_insert(&h, &path[y][x]); } else { path[y][x].hn = NULL; } } } while ((p = (corridor_path_t *) heap_remove_min(&h))) { p->hn = NULL; if ((p->pos[dim_y] == to[dim_y]) && p->pos[dim_x] == to[dim_x]) { for (x = to[dim_x], y = to[dim_y]; (x != from[dim_x]) || (y != from[dim_y]); p = &path[y][x], x = p->from[dim_x], y = p->from[dim_y]) { if (mapxy(x, y) != ter_floor_room) { mapxy(x, y) = ter_floor_hall; hardnessxy(x, y) = 0; } } heap_delete(&h); return; } if ((path[p->pos[dim_y] - 1][p->pos[dim_x] ].hn) && (path[p->pos[dim_y] - 1][p->pos[dim_x] ].cost > p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_x] != from[dim_x]) ? 48 : 0))) { path[p->pos[dim_y] - 1][p->pos[dim_x] ].cost = p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_x] != from[dim_x]) ? 48 : 0); path[p->pos[dim_y] - 1][p->pos[dim_x] ].from[dim_y] = p->pos[dim_y]; path[p->pos[dim_y] - 1][p->pos[dim_x] ].from[dim_x] = p->pos[dim_x]; heap_decrease_key_no_replace(&h, path[p->pos[dim_y] - 1] [p->pos[dim_x] ].hn); } if ((path[p->pos[dim_y] ][p->pos[dim_x] - 1].hn) && (path[p->pos[dim_y] ][p->pos[dim_x] - 1].cost > p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_y] != from[dim_y]) ? 48 : 0))) { path[p->pos[dim_y] ][p->pos[dim_x] - 1].cost = p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_y] != from[dim_y]) ? 48 : 0); path[p->pos[dim_y] ][p->pos[dim_x] - 1].from[dim_y] = p->pos[dim_y]; path[p->pos[dim_y] ][p->pos[dim_x] - 1].from[dim_x] = p->pos[dim_x]; heap_decrease_key_no_replace(&h, path[p->pos[dim_y] ] [p->pos[dim_x] - 1].hn); } if ((path[p->pos[dim_y] ][p->pos[dim_x] + 1].hn) && (path[p->pos[dim_y] ][p->pos[dim_x] + 1].cost > p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_y] != from[dim_y]) ? 48 : 0))) { path[p->pos[dim_y] ][p->pos[dim_x] + 1].cost = p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_y] != from[dim_y]) ? 48 : 0); path[p->pos[dim_y] ][p->pos[dim_x] + 1].from[dim_y] = p->pos[dim_y]; path[p->pos[dim_y] ][p->pos[dim_x] + 1].from[dim_x] = p->pos[dim_x]; heap_decrease_key_no_replace(&h, path[p->pos[dim_y] ] [p->pos[dim_x] + 1].hn); } if ((path[p->pos[dim_y] + 1][p->pos[dim_x] ].hn) && (path[p->pos[dim_y] + 1][p->pos[dim_x] ].cost > p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_x] != from[dim_x]) ? 48 : 0))) { path[p->pos[dim_y] + 1][p->pos[dim_x] ].cost = p->cost + (hardnesspair(p->pos) ? hardnesspair(p->pos) : 8) + ((p->pos[dim_x] != from[dim_x]) ? 48 : 0); path[p->pos[dim_y] + 1][p->pos[dim_x] ].from[dim_y] = p->pos[dim_y]; path[p->pos[dim_y] + 1][p->pos[dim_x] ].from[dim_x] = p->pos[dim_x]; heap_decrease_key_no_replace(&h, path[p->pos[dim_y] + 1] [p->pos[dim_x] ].hn); } } }
void dijkstra_tunnel(dungeon_t *d) { /* Currently assumes that monsters only move on floors. Will * * need to be modified for tunneling and pass-wall monsters. */ heap_t h; uint32_t x, y; static path_t p[DUNGEON_Y][DUNGEON_X], *c; static uint32_t initialized = 0; if (!initialized) { initialized = 1; dungeon = d; for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { p[y][x].pos[dim_y] = y; p[y][x].pos[dim_x] = x; } } } for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { d->pc_tunnel[y][x] = 255; } } d->pc_tunnel[character_get_y(d->pc)][character_get_x(d->pc)] = 0; heap_init(&h, tunnel_cmp, NULL); for (y = 0; y < DUNGEON_Y; y++) { for (x = 0; x < DUNGEON_X; x++) { if (mapxy(x, y) != ter_wall_immutable) { p[y][x].hn = heap_insert(&h, &p[y][x]); } } } while ((c = heap_remove_min(&h))) { c->hn = NULL; if ((p[c->pos[dim_y] - 1][c->pos[dim_x] - 1].hn) && (d->pc_tunnel[c->pos[dim_y] - 1][c->pos[dim_x] - 1] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] - 1][c->pos[dim_x] - 1] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] - 1][c->pos[dim_x] ].hn) && (d->pc_tunnel[c->pos[dim_y] - 1][c->pos[dim_x] ] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] - 1][c->pos[dim_x] ] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] ].hn); } if ((p[c->pos[dim_y] - 1][c->pos[dim_x] + 1].hn) && (d->pc_tunnel[c->pos[dim_y] - 1][c->pos[dim_x] + 1] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] - 1][c->pos[dim_x] + 1] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] - 1][c->pos[dim_x] + 1].hn); } if ((p[c->pos[dim_y] ][c->pos[dim_x] - 1].hn) && (d->pc_tunnel[c->pos[dim_y] ][c->pos[dim_x] - 1] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] ][c->pos[dim_x] - 1] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] ][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] ][c->pos[dim_x] + 1].hn) && (d->pc_tunnel[c->pos[dim_y] ][c->pos[dim_x] + 1] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] ][c->pos[dim_x] + 1] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] ][c->pos[dim_x] + 1].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] - 1].hn) && (d->pc_tunnel[c->pos[dim_y] + 1][c->pos[dim_x] - 1] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] + 1][c->pos[dim_x] - 1] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] - 1].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] ].hn) && (d->pc_tunnel[c->pos[dim_y] + 1][c->pos[dim_x] ] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] + 1][c->pos[dim_x] ] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] ].hn); } if ((p[c->pos[dim_y] + 1][c->pos[dim_x] + 1].hn) && (d->pc_tunnel[c->pos[dim_y] + 1][c->pos[dim_x] + 1] > d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60))) { d->pc_tunnel[c->pos[dim_y] + 1][c->pos[dim_x] + 1] = (d->pc_tunnel[c->pos[dim_y]][c->pos[dim_x]] + 1 + (d->hardness[c->pos[dim_y]][c->pos[dim_x]] / 60)); heap_decrease_key_no_replace(&h, p[c->pos[dim_y] + 1][c->pos[dim_x] + 1].hn); } } heap_delete(&h); }