#include #include #include #include #include "map.h" #include "config.h" #include "stack.h" Map empty_map(size_t width, size_t height) { Map map = malloc(sizeof(MapTile*) * height); if (map == NULL) return NULL; for (size_t row = 0; row < height; row++) { map[row] = malloc(sizeof(MapTile) * width); if (map[row] == NULL) return NULL; memset(map[row], 0, width*sizeof(MapTile)); } return map; } unsigned int neighbours(Position neighbour_array[], Position pos, size_t width, size_t height, \ char visited[height][width]) { //TODO: add thing for when visited is NULL 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; 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; 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; 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; cur += 1; } return cur; } Map rbt_maze_map(size_t width, size_t height, unsigned int seed) { size_t map_width = width * 2 - 1, map_height = height * 2 - 1; Map map = empty_map(map_width, map_height); // Vertical walls for (size_t i = 1; i < map_width; i += 2) { for (size_t j = 0; j < map_height; j += 1) { map[j][i] = WALL; } } // Horizontal walls for (size_t i = 1; i < map_height; i += 2) { for (size_t j = 0; j < map_width; j += 1) { map[i][j] = WALL; } } Position beginning_cell = {width - 1, height - 1}; char visited[height][width]; // 1 if visited, 0 if not memset(visited, 0, sizeof(char) * width * height); PositionStack ps = ps_new(); ps_push(&ps, beginning_cell); visited[beginning_cell.y][beginning_cell.x] = 1; Position na[4]; srand(seed); do { int nc = neighbours(na, ps_peek(ps), width, height, visited); if (nc > 0) { Position next = na[rand() % nc]; Position prev = ps_peek(ps); ps_push(&ps, next); visited[next.y][next.x] = 1; map[(next.y * 2 + prev.y * 2) / 2][(next.x * 2 + prev.x * 2) / 2] = EMPTY; } else { (void)ps_pop(&ps); } } while (ps_peek(ps).x != beginning_cell.x || ps_peek(ps).y != beginning_cell.y) ; return map; } void draw_map(Map map, size_t width, size_t height, Position start, Position goal) { // Draw the walls around the map (they are not in map) attron(COLOR_PAIR(WALL_COLOR)); for (size_t i = 0; i <= width*2 + 3; i++) { mvaddch(DRAW_MAP_OFFSET_X - 2, i, WALL_CHAR); mvaddch(DRAW_MAP_OFFSET_Y + height, i, WALL_CHAR); } for (size_t i = 1; i <= height; i++) { mvaddch(i, DRAW_MAP_OFFSET_X - 2, WALL_CHAR); mvaddch(i, DRAW_MAP_OFFSET_X - 1, WALL_CHAR); mvaddch(i, DRAW_MAP_OFFSET_X + width * 2, WALL_CHAR); mvaddch(i, DRAW_MAP_OFFSET_X + width * 2 + 1, WALL_CHAR); } attroff(COLOR_PAIR(WALL_COLOR)); // Draw field char c; // The char for the current tile for (size_t i = 0; i < height; i++) { for (size_t j = 0; j < width; j++) { int color_pair = 0; // The color pair of the current char switch (map[i][j]) { case EMPTY: color_pair = COLOR_PAIR(EMPTY_COLOR); c = EMPTY_CHAR; break; case WALL: color_pair = COLOR_PAIR(WALL_COLOR); c = WALL_CHAR; break; } attron(color_pair); /* We draw two characters because they roughly make a square together. * It looks WAY better if we do this. */ mvaddch(i + DRAW_MAP_OFFSET_Y, j*2 + DRAW_MAP_OFFSET_X, c); mvaddch(i + DRAW_MAP_OFFSET_Y, j*2 + DRAW_MAP_OFFSET_X + 1, c); attroff(color_pair); } } // Draw the start attron(COLOR_PAIR(START_COLOR)); mvaddch(start.y + DRAW_MAP_OFFSET_Y, start.x*2 + DRAW_MAP_OFFSET_X, START_CHAR_1); mvaddch(start.y + DRAW_MAP_OFFSET_Y, start.x*2 + DRAW_MAP_OFFSET_X + 1, START_CHAR_2); attroff(COLOR_PAIR(START_COLOR)); /* Draw the goal */ attron(COLOR_PAIR(GOAL_COLOR)); mvaddch(goal.y + DRAW_MAP_OFFSET_Y, goal.x*2 + DRAW_MAP_OFFSET_X, GOAL_CHAR_1); mvaddch(goal.y + DRAW_MAP_OFFSET_Y, goal.x*2 + DRAW_MAP_OFFSET_X + 1, GOAL_CHAR_2); attroff(COLOR_PAIR(GOAL_COLOR)); }