1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include <string.h>
#include <stdlib.h>
#include <curses.h>
#include <limits.h>
#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, int width, int height, Position start) {
// Draw field
char c; // The char for the current tile
for (int i = 0; i < height; i++) {
for (int 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 GOAL:
color_pair = COLOR_PAIR(GOAL_COLOR);
c = GOAL_CHAR;
break;
case WALL:
color_pair = COLOR_PAIR(WALL_COLOR);
c = WALL_CHAR;
break;
}
attron(color_pair);
mvaddch(i + DRAW_MAP_OFFSET_Y, j + DRAW_MAP_OFFSET_X, c);
attroff(color_pair);
}
}
// Draw the start
attron(COLOR_PAIR(START_COLOR));
mvaddch(start.y + DRAW_MAP_OFFSET_Y, start.x + DRAW_MAP_OFFSET_X, START_CHAR);
attroff(COLOR_PAIR(START_COLOR));
}
|