diff options
| -rw-r--r-- | main.c | 20 | ||||
| -rw-r--r-- | map.c | 80 | ||||
| -rw-r--r-- | map.h | 4 | ||||
| -rw-r--r-- | path.c | 59 | ||||
| -rw-r--r-- | path.h | 14 |
5 files changed, 107 insertions, 70 deletions
@@ -19,7 +19,7 @@ - Maybe make map editor the main thing - More messages - check ppq_insert() order - - more info in anim() + - more info in anim()? - save pathfinding to a series of BMPs - less magical values - MORE MAPS FOR THE MAP PEOPLE @@ -135,11 +135,13 @@ int main(int argc, char **argv) { if (!bmp_only) { init_ncurses(); + draw_map(map, width, height, start_pos, end_pos, NULL, NULL, NULL, NULL); + wrefresh(stdscr); } char **visited = visited_new(width, height); Path path = NULL; - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); if (bmp_only) { map_to_bmp(map, width, height, start_pos, end_pos, path, visited, bmp_filename); @@ -154,8 +156,6 @@ int main(int argc, char **argv) { while (1) { draw_map(map, width, height, start_pos, end_pos, NULL, path, visited, NULL); int c = getch(); - /* TODO: add a keybinding to calculate the path again, or maybe do it on 'a' */ - /* TODO: add a keybinding to load a map from a file */ switch (c) { case 'h': map_offset_x += 2; break; case 'l': map_offset_x -= 2; break; @@ -191,7 +191,7 @@ int main(int argc, char **argv) { else anim = 1; path_free(path, height); - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); clear_message(); break; @@ -199,7 +199,7 @@ int main(int argc, char **argv) { if (path_func == astar_path) { set_message("Dijkstra"); path_func = &dijkstra_path; } else { set_message("A*"); path_func = &astar_path; }; path_free(path, height); - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); break; case 'y': @@ -224,7 +224,7 @@ int main(int argc, char **argv) { map = rbt_maze_map(mwidth, mheight, rand()); visited = visited_new(width, height); - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); } break; @@ -260,7 +260,7 @@ int main(int argc, char **argv) { map = file_plaintext_map(filename, &width, &height, &start_pos, &end_pos); visited = visited_new(width, height); - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); set_message("Loaded map from %s", filename); print_message(height); @@ -274,7 +274,7 @@ int main(int argc, char **argv) { map_free(map, height); map = rbt_maze_map(mwidth, mheight, rand()); path_free(path, height); - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); } break; @@ -288,7 +288,7 @@ int main(int argc, char **argv) { wrefresh(curscr); visited = visited_new(width, height); - path = path_func(dirs, map, width, height, start_pos, end_pos, visited, anim); + path = path_func(dirs, map, NULL, width, height, start_pos, end_pos, visited, anim); break; case KEY_RESIZE: clear(); break; @@ -31,30 +31,42 @@ Map empty_map(size_t width, size_t height) { /* When we allow maps to have costs, these two neighbours functions will have to use the instead of COST_* defines */ /* TODO: maybe merge them, add `dirs` parameter, like we do in path.c? */ unsigned int neighbours_4dir(Position neighbour_array[4], size_t cost_array[4], Position pos, size_t width, size_t height, \ - char **visited) { + char **visited, size_t **costs) { size_t cur = 0; if (pos.x > 0 && !visited[pos.y][pos.x - 1]) { neighbour_array[cur].x = pos.x - 1; neighbour_array[cur].y = pos.y; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y][pos.x - 1]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.x + 1 < width && !visited[pos.y][pos.x + 1]) { neighbour_array[cur].x = pos.x + 1; neighbour_array[cur].y = pos.y; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y][pos.x + 1]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.y > 0 && !visited[pos.y - 1][pos.x]) { neighbour_array[cur].x = pos.x; neighbour_array[cur].y = pos.y - 1; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y - 1][pos.x]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.y + 1 < height && !visited[pos.y + 1][pos.x]) { neighbour_array[cur].x = pos.x; neighbour_array[cur].y = pos.y + 1; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y + 1][pos.x]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } @@ -62,55 +74,79 @@ unsigned int neighbours_4dir(Position neighbour_array[4], size_t cost_array[4], } unsigned int neighbours_8dir(Position neighbour_array[8], size_t cost_array[8], Position pos, size_t width, size_t height, \ - char **visited) { + char **visited, size_t **costs) { size_t cur = 0; if (pos.x > 0 && !visited[pos.y][pos.x - 1]) { neighbour_array[cur].x = pos.x - 1; neighbour_array[cur].y = pos.y; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y][pos.x - 1]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.x + 1 < width && !visited[pos.y][pos.x + 1]) { neighbour_array[cur].x = pos.x + 1; neighbour_array[cur].y = pos.y; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y][pos.x + 1]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.y > 0 && !visited[pos.y - 1][pos.x]) { neighbour_array[cur].x = pos.x; neighbour_array[cur].y = pos.y - 1; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y - 1][pos.x]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.y + 1 < height && !visited[pos.y + 1][pos.x]) { neighbour_array[cur].x = pos.x; neighbour_array[cur].y = pos.y + 1; - if (cost_array != NULL) cost_array[cur] = COST_ORTHOGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y + 1][pos.x]; + else cost_array[cur] = COST_ORTHOGONAL; + } cur += 1; } if (pos.x > 0 && pos.y > 0 && !visited[pos.y - 1][pos.x - 1]) { neighbour_array[cur].x = pos.x - 1; neighbour_array[cur].y = pos.y - 1; - if (cost_array != NULL) cost_array[cur] = COST_DIAGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y - 1][pos.x - 1]; + else cost_array[cur] = COST_DIAGONAL; + } cur += 1; } if (pos.x + 1 < width && pos.y > 0 && !visited[pos.y - 1][pos.x + 1]) { neighbour_array[cur].x = pos.x + 1; neighbour_array[cur].y = pos.y - 1; - if (cost_array != NULL) cost_array[cur] = COST_DIAGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y - 1][pos.x + 1]; + else cost_array[cur] = COST_DIAGONAL; + } cur += 1; } if (pos.x + 1 < width && pos.y + 1 < height && !visited[pos.y + 1][pos.x + 1]) { neighbour_array[cur].x = pos.x + 1; neighbour_array[cur].y = pos.y + 1; - if (cost_array != NULL) cost_array[cur] = COST_DIAGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y + 1][pos.x + 1]; + else cost_array[cur] = COST_DIAGONAL; + } cur += 1; } if (pos.x > 0 && pos.y + 1 < height && !visited[pos.y + 1][pos.x - 1]) { neighbour_array[cur].x = pos.x - 1; neighbour_array[cur].y = pos.y + 1; - if (cost_array != NULL) cost_array[cur] = COST_DIAGONAL; + if (cost_array != NULL) { + if (costs != NULL) cost_array[cur] = costs[pos.y + 1][pos.x - 1]; + else cost_array[cur] = COST_DIAGONAL; + } cur += 1; } @@ -149,7 +185,7 @@ Map rbt_maze_map(size_t width, size_t height, unsigned int seed) { srand(seed); do { - int nc = neighbours_4dir(na, NULL, ps_peek(ps), width, height, visited); + int nc = neighbours_4dir(na, NULL, ps_peek(ps), width, height, visited, NULL); if (nc > 0) { Position next = na[rand() % nc]; Position prev = ps_peek(ps); @@ -477,7 +513,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi if (should_pathfind) { set_message("Will pathfind"); visited = visited_new(*width, *height); - path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); } else { set_message("Won't pathfind"); visited_free(visited, *height); visited = NULL; @@ -505,7 +541,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi if (path_func == astar_path) { set_message("Dijkstra"); path_func = &dijkstra_path; } else { set_message("A*"); path_func = &astar_path; }; path_free(path, *height); - if (should_pathfind) path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + if (should_pathfind) path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); break; case 's': @@ -542,7 +578,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi if (row < *height && col < *width && (*map)[row][col] != WALL && (col != goal->x || row != goal->y)) { start->x = col; start->y = row; - if (should_pathfind) path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + if (should_pathfind) path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); draw_map(*map, *width, *height, *start, *goal, NULL, path, visited, NULL); } } @@ -553,7 +589,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi if (row < *height && col < *width && (*map)[row][col] != WALL && (col != start->x || row != start->y)) { goal->x = col; goal->y = row; - if (should_pathfind) path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + if (should_pathfind) path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); draw_map(*map, *width, *height, *start, *goal, NULL, path, visited, NULL); } } @@ -596,7 +632,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi if (should_pathfind) { visited = visited_new(*width, *height); - path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); } draw_map(*map, *width, *height, *start, *goal, NULL, path, visited, NULL); } else if (col == *width) { /* Resize horizontally */ @@ -642,7 +678,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi if (should_pathfind) { visited = visited_new(*width, *height); - path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); } draw_map(*map, *width, *height, *start, *goal, NULL, path, visited, NULL); } else { /* Start drawing */ @@ -665,7 +701,7 @@ void map_editor(Map *map, size_t *width, size_t *height, Position *start, Positi (*map)[row][col] = cur; path_free(path, *height); if (should_pathfind) { - path = path_func(dirs, *map, *width, *height, *start, *goal, visited, 0); + path = path_func(dirs, *map, NULL, *width, *height, *start, *goal, visited, 0); } draw_map(*map, *width, *height, *start, *goal, NULL, path, visited, NULL); } @@ -19,12 +19,12 @@ Map empty_map(size_t width, size_t height); /* Stores all the existing 4dir neighbours of pos in neighbour_array and returns their amount */ unsigned int neighbours_4dir(Position neighbour_array[4], size_t cost_array[4], Position pos, size_t width, size_t height, \ - char **visited); + char **visited, size_t **costs); /* Stores all the existing 8dir neighbours of pos in neighbour_array and returns their amount. * Additionaly stores costs into cost_array if it's not NULL. * The cost of goint orthogonally is 10, diagonaly is 14 (sqrt(2) * 10) */ unsigned int neighbours_8dir(Position neighbour_array[8], size_t cost_array[8], Position pos, size_t width, size_t height, \ - char **visited); + char **visited, size_t **costs); /* https://en.wikipedia.org/wiki/Maze_generation_algorithm#Randomized_depth-first_search * WARNING: width and height are not the width and height of the returned map! @@ -12,7 +12,7 @@ #include "error.h" #include "config.h" -Path (*path_func)(int, Map, size_t, size_t, Position, Position, char **, char) = &astar_path; +Path (*path_func)(int, Map, size_t **, size_t, size_t, Position, Position, char **, char) = &astar_path; char anim_automatic = 0; @@ -62,11 +62,12 @@ int anim(Map map, size_t width, size_t height, Position start, Position end, Pos return 0; } /* BLOODY FUCK IT WORKS */ -Path breadth_first_search_path(int dirs, Map map, size_t width, size_t height, Position start, Position end, char **visited, char should_anim) { +Path breadth_first_search_path(int dirs, Map map, size_t **cell_costs, size_t width, size_t height, Position start, Position end, char **visited, char should_anim) { + (void)cell_costs; /* BFS doesn't support costs */ anim_automatic = 0; /* The function to use to find neighbours */ - unsigned int (*neighbours)(Position[], size_t[], Position, size_t, size_t, char**) = NULL; + unsigned int (*neighbours)(Position[], size_t[], Position, size_t, size_t, char**, size_t**) = NULL; switch (dirs) { case 4: neighbours = &neighbours_4dir; break; case 8: neighbours = &neighbours_8dir; break; @@ -93,7 +94,7 @@ Path breadth_first_search_path(int dirs, Map map, size_t width, size_t height, P } Position na[dirs]; - unsigned int nc = neighbours(na, NULL, cur, width, height, visited); + unsigned int nc = neighbours(na, NULL, cur, width, height, visited, NULL); for (unsigned int i = 0; i < nc; i++) { /* The Russian constitution doesn't allow walking on walls */ @@ -121,11 +122,11 @@ Path breadth_first_search_path(int dirs, Map map, size_t width, size_t height, P return NULL; } -Path dijkstra_path(int dirs, Map map, size_t width, size_t height, Position start, Position end, char **visited, char should_anim) { +Path dijkstra_path(int dirs, Map map, size_t **cell_costs, size_t width, size_t height, Position start, Position end, char **visited, char should_anim) { anim_automatic = 0; /* The function to use to find neighbours */ - unsigned int (*neighbours)(Position[], size_t[], Position, size_t, size_t, char**) = NULL; + unsigned int (*neighbours)(Position[], size_t[], Position, size_t, size_t, char**, size_t**) = NULL; switch (dirs) { case 4: neighbours = &neighbours_4dir; break; @@ -139,7 +140,7 @@ Path dijkstra_path(int dirs, Map map, size_t width, size_t height, Position star PositionPQ *frontier = ppq_new(start, 0); visited_clear(visited, width, height); - size_t **cost_so_far = cost_so_far_new(width, height); + size_t **cost_so_far = cost_new(width, height); cost_so_far[start.y][start.x] = 0; while (frontier != NULL) { @@ -148,13 +149,13 @@ Path dijkstra_path(int dirs, Map map, size_t width, size_t height, Position star if (cur.x == end.x && cur.y == end.y) { ppq_free(frontier); - cost_so_far_free(cost_so_far, height); + cost_free(cost_so_far, height); return path; /* Found path */ } Position na[dirs]; size_t costs[dirs]; - unsigned int nc = neighbours(na, costs, cur, width, height, visited); + unsigned int nc = neighbours(na, costs, cur, width, height, visited, cell_costs); for (unsigned int i = 0; i < nc; i++) { /* The Russian constitution doesn't allow walking on walls */ @@ -173,7 +174,7 @@ Path dijkstra_path(int dirs, Map map, size_t width, size_t height, Position star clear(); path_free(path, height); ppq_free(frontier); - cost_so_far_free(cost_so_far, height); + cost_free(cost_so_far, height); return NULL; } } @@ -181,15 +182,15 @@ Path dijkstra_path(int dirs, Map map, size_t width, size_t height, Position star path_free(path, height); ppq_free(frontier); - cost_so_far_free(cost_so_far, height); + cost_free(cost_so_far, height); return NULL; } -Path astar_path(int dirs, Map map, size_t width, size_t height, Position start, Position end, char **visited, char should_anim) { +Path astar_path(int dirs, Map map, size_t **cell_costs, size_t width, size_t height, Position start, Position end, char **visited, char should_anim) { anim_automatic = 0; /* The function to use to find neighbours */ - unsigned int (*neighbours)(Position[], size_t[], Position, size_t, size_t, char**) = NULL; + unsigned int (*neighbours)(Position[], size_t[], Position, size_t, size_t, char**, size_t**) = NULL; /* The heuristic function */ size_t (*heuristic)(Position, Position) = NULL; @@ -206,7 +207,7 @@ Path astar_path(int dirs, Map map, size_t width, size_t height, Position start, PositionPQ *frontier = ppq_new(start, 0); visited_clear(visited, width, height); - size_t **cost_so_far = cost_so_far_new(width, height); + size_t **cost_so_far = cost_new(width, height); cost_so_far[start.y][start.x] = 0; while (frontier != NULL) { @@ -215,13 +216,13 @@ Path astar_path(int dirs, Map map, size_t width, size_t height, Position start, if (cur.x == end.x && cur.y == end.y) { ppq_free(frontier); - cost_so_far_free(cost_so_far, height); + cost_free(cost_so_far, height); return path; /* Found path */ } Position na[dirs]; size_t costs[dirs]; - unsigned int nc = neighbours(na, costs, cur, width, height, visited); + unsigned int nc = neighbours(na, costs, cur, width, height, visited, cell_costs); for (unsigned int i = 0; i < nc; i++) { /* The Russian constitution doesn't allow walking on walls */ @@ -241,7 +242,7 @@ Path astar_path(int dirs, Map map, size_t width, size_t height, Position start, clear(); path_free(path, height); ppq_free(frontier); - cost_so_far_free(cost_so_far, height); + cost_free(cost_so_far, height); return NULL; } } @@ -249,7 +250,7 @@ Path astar_path(int dirs, Map map, size_t width, size_t height, Position start, path_free(path, height); ppq_free(frontier); - cost_so_far_free(cost_so_far, height); + cost_free(cost_so_far, height); return NULL; } @@ -362,24 +363,24 @@ size_t visited_count(char **visited, size_t width, size_t height) { return count; } -size_t **cost_so_far_new(size_t width, size_t height) { - size_t **cost_so_far = malloc(sizeof(size_t*) * height); - if (cost_so_far == NULL) return NULL; +size_t **cost_new(size_t width, size_t height) { + size_t **cost = malloc(sizeof(size_t*) * height); + if (cost == NULL) return NULL; for (size_t row = 0; row < height; row++) { - cost_so_far[row] = malloc(sizeof(size_t) * width); - if (cost_so_far[row] == NULL) return NULL; - memset(cost_so_far[row], 0xFF, width*sizeof(size_t)); + cost[row] = malloc(sizeof(size_t) * width); + if (cost[row] == NULL) return NULL; + memset(cost[row], 0xFF, width*sizeof(size_t)); } - return cost_so_far; + return cost; } -void cost_so_far_free(size_t **cost_so_far, size_t height) { - if (cost_so_far == NULL) return; +void cost_free(size_t **cost, size_t height) { + if (cost == NULL) return; for (size_t row = 0; row < height; row++) { - free(cost_so_far[row]); + free(cost[row]); } - free(cost_so_far); + free(cost); return; } @@ -5,12 +5,12 @@ #include "map.h" /* The currently chosen path func */ -extern Path (*path_func)(int, Map, size_t, size_t, Position, Position, char **, char); +extern Path (*path_func)(int, Map, size_t **, size_t, size_t, Position, Position, char **, char); /* dirs can be 4 or 8 to disallow or allow diagonal movement */ -Path breadth_first_search_path(int dirs, Map map, size_t width, size_t height, Position start, Position end, char **visited, char should_anim); -Path dijkstra_path(int dirs, Map map, size_t width, size_t height, Position start, Position end, char **visited, char should_anim); -Path astar_path(int dirs, Map map, size_t width, size_t height, Position start, Position end, char **visited, char should_anim); +Path breadth_first_search_path(int dirs, Map map, size_t **cell_costs, size_t width, size_t height, Position start, Position end, char **visited, char should_anim); +Path dijkstra_path(int dirs, Map map, size_t **cell_costs, size_t width, size_t height, Position start, Position end, char **visited, char should_anim); +Path astar_path(int dirs, Map map, size_t **cell_costs, size_t width, size_t height, Position start, Position end, char **visited, char should_anim); size_t manhattan_distance(Position a, Position b); size_t diagonal_distance(Position a, Position b); @@ -26,8 +26,8 @@ void visited_clear(char **visited, size_t width, size_t height); void visited_free(char **visited, size_t height); size_t visited_count(char **visited, size_t width, size_t height); -/* Helper funcs for the cost_so_far array */ -size_t **cost_so_far_new(size_t width, size_t height); -void cost_so_far_free(size_t **cost_so_far, size_t height); +/* Helper funcs for the cost arrays */ +size_t **cost_new(size_t width, size_t height); +void cost_free(size_t **cost, size_t height); #endif /* ASTAR_H_ */ |
