#include #include #include #include #include #include #include #include "map.h" #include "structs.h" #include "config.h" #include "error.h" #include "priority_queue.h" #include "path.h" /* So, TODO for now: - Keybinds to increase map size - Allow maps to have costs - Implement greedy-best-first algorithm (4 and 8 dir) - Implement Dijkstra algorithm (4 and 8 dir) - Implement the A* algorithm (4 and 8 dir) - MORE MAPS FOR THE MAP PEOPLE - Implement controls (to change maps, move start/goal, etc.) - Clean up unused `#include`s - mouse controls to edit map, drag start and end around */ void sigint_handler(int sig) { (void)sig; /* We know it's a SIGINT */ endwin(); printf("Received SIGINT\n"); exit(1); } void initialize_colors(void) { start_color(); use_default_colors(); init_pair(EMPTY_COLOR, COLOR_BLACK, -1); init_pair(VISITED_COLOR, COLOR_GREEN, COLOR_GREEN); init_pair(GOAL_COLOR, -1, COLOR_RED); init_pair(WALL_COLOR, COLOR_WHITE, COLOR_WHITE); init_pair(START_COLOR, -1, COLOR_RED); init_pair(PATH_COLOR, COLOR_RED, COLOR_RED); init_pair(FRONTIER_COLOR, COLOR_BLUE, COLOR_BLUE); init_pair(CURSOR_COLOR, -1, COLOR_RED); } void init_ncurses(void) { initscr(); /* Initialize the ncurses screen */ cbreak(); /* Process input one char at a time */ curs_set(0); /* Hide the cursor */ noecho(); /* Don't echo characters */ initialize_colors(); } int main(int argc, char **argv) { Position start_pos, end_pos; size_t width, height; Map map = NULL; size_t mwidth = 20; /* Maze width */ size_t mheight = 10; /* Maze height */ char is_maze = 0; char anim = 0; int dirs = 8; srand(time(NULL)); /* Handle args. * Currently supported: * -a to animate the pathfinding (get input after each step) * -m {width}x{height} to give a maze of given size * -f {filename} to load a map from the filename * -4 for four directions * -8 for eight directions */ /* TODO: Argument to choose the algorithm */ int opt; while ((opt = getopt(argc, argv, ":am:f:48")) != -1) { switch (opt) { case 'a': anim = 1; break; case 'm': if (sscanf(optarg, "%zux%zu", &mwidth, &mheight) != 2) error("Wrong maze size string in argument\n"); is_maze = 1; map = rbt_maze_map(mwidth, mheight, (unsigned int) time(NULL)); start_pos.x = 0; start_pos.y = 0; height = mheight * 2 - 1; width = mwidth * 2 - 1; end_pos.x = width - 1; end_pos.y = height - 1; break; case 'f': map = file_plaintext_map(optarg, &width, &height, &start_pos, &end_pos); break; case '4': dirs = 4; break; case '8': dirs = 8; break; case '?': error("Unknown option: %c\n", optopt); case ':': error("Option %c requires an argument\n", optopt); } } if (map == NULL) { /* If no map were given */ is_maze = 1; if (argc == 4) { /* maze size as argv[2] and [3] */ mwidth = atoi(argv[2]); mheight = atoi(argv[3]); } map = rbt_maze_map(mwidth, mheight, rand()); start_pos.x = 0; start_pos.y = 0; height = mheight * 2 - 1; width = mwidth * 2 - 1; end_pos.x = width - 1; end_pos.y = height - 1; } signal(SIGINT, sigint_handler); init_ncurses(); int offset_x = 0, offset_y = 0; draw_map(map, width, height, offset_x, offset_y, start_pos, end_pos, NULL, NULL, NULL, NULL); //print_map_out(map, width, height); char visited[height][width]; Path path = NULL; path = breadth_first_search_path(dirs, map, width, height, start_pos, end_pos, visited, anim); while (1) { draw_map(map, width, height, offset_x, offset_y, start_pos, end_pos, NULL, path, visited, NULL); char c = getch(); switch (c) { case 'h': offset_x -= 2; break; case 'l': offset_x += 2; break; case 'j': offset_y += 1; break; case 'k': offset_y -= 1; break; case 'a': anim = !anim; break; case 'n': if (is_maze) { map_free(map, height); map = rbt_maze_map(mwidth, mheight, rand()); path_free(path, height); path = breadth_first_search_path(dirs, map, width, height, start_pos, end_pos, visited, anim); } break; case 'q': map_free(map, height); path_free(path, height); endwin(); return 0; } } endwin(); return 0; }