Implements functionality for generating the game map.
More...
#include "map_generator.h"
#include "../logging/logger.h"
#include "map.h"
#include "map_mode.h"
#include "map_populator.h"
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
Go to the source code of this file.
|
void | shuffle (vector2d_t *dir, int n) |
| Shuffle array using Fisher-Yates algorithm.
|
int | is_in_bounds (int x, int y) |
| Check if cell is within bounds of the map.
|
int | is_valid_cell (int x, int y) |
| Check if a cell is a valid cell to visit (in bounds and not visited)
|
int | validate_exit_position (int exit_e, int x, int y) |
| Check if the exit position is adjacent to a floor cell.
|
void | carve_passages (int x, int y) |
| Recursive backtracking algorithm to generate map (based on dfs)
|
int | check_neighboring_floors (int x, int y, int neighbor_directions[4]) |
| Count neighboring floor cells.
|
void | add_loops (int num_loops) |
| Add loops to the map by knocking down some walls.
|
void | place_exit (int start_edge) |
| Place the exit on a random edge of the map, ensuring there's a path to it.
|
void | initialize_map () |
| Initialize the map with walls.
|
void | generate_maze (int start_x, int start_y) |
| Generate a new maze using recursive backtracking.
|
void | set_start_position (int start_edge, int *start_x, int *start_y) |
| Set the start position on the map.
|
void | make_exit_into_start (int *start_edge, int *start_x, int *start_y) |
| Set the start position on the map based on the previous exit position.
|
void | generate_map () |
| Generate the map and populate it with keys, enemies, and the exit.
|
Implements functionality for generating the game map.
Definition in file map_generator.c.
◆ add_loops()
void add_loops |
( |
int | num_loops | ) |
|
Add loops to the map by knocking down some walls.
- Parameters
-
num_loops | number of loops to add |
Definition at line 142 of file map_generator.c.
142 {
143 int count = 0;
144 int max_attempts = num_loops * 10;
145
146 while (count < num_loops && max_attempts > 0) {
147
148 int x = 1 + rand() % (WIDTH - 2);
149 int y = 1 + rand() % (HEIGHT - 2);
150
151
152 if (map[x][y] == WALL) {
153 int neighbor_directions[] = {0, 0, 0, 0};
154
156
157
158 if ((floor_count == 2) &&
159 ((neighbor_directions[TOP] && neighbor_directions[BOTTOM]) ||
160 (neighbor_directions[LEFT] && neighbor_directions[RIGHT]))) {
161 map[x][y] = FLOOR;
162 count++;
163 }
164 }
165
166 max_attempts--;
167 }
168}
int check_neighboring_floors(int x, int y, int neighbor_directions[4])
Count neighboring floor cells.
◆ carve_passages()
void carve_passages |
( |
int | x, |
|
|
int | y ) |
Recursive backtracking algorithm to generate map (based on dfs)
- Parameters
-
x | starting x coordinate |
y | starting y coordinate |
Definition at line 89 of file map_generator.c.
89 {
90 visited[x][y] = 1;
91 map[x][y] = FLOOR;
92
93
95 for (int i = 0; i < 4; i++) {
96 shuffled_dirs[i] = directions[i];
97 }
99
100
101 for (int i = 0; i < 4; i++) {
102 int nx = x + shuffled_dirs[i].dx * 2;
103 int ny = y + shuffled_dirs[i].dy * 2;
104
106
107 int wall_x = x + shuffled_dirs[i].dx;
108 int wall_y = y + shuffled_dirs[i].dy;
109
110
111 map[wall_x][wall_y] = FLOOR;
113 }
114 }
115}
int is_valid_cell(int x, int y)
Check if a cell is a valid cell to visit (in bounds and not visited)
void shuffle(vector2d_t *dir, int n)
Shuffle array using Fisher-Yates algorithm.
void carve_passages(int x, int y)
Recursive backtracking algorithm to generate map (based on dfs)
2-dimensional vector struct
◆ check_neighboring_floors()
int check_neighboring_floors |
( |
int | x, |
|
|
int | y, |
|
|
int | neighbor_directions[4] ) |
Count neighboring floor cells.
- Parameters
-
x | x coordinate of the cell |
y | y coordinate of the cell |
neighbor_directions | bool array to store on which sides the neighbors are |
- Returns
- number of neighboring floor cells
Definition at line 124 of file map_generator.c.
124 {
125 int count = 0;
126 for (int i = 0; i < 4; i++) {
127 int dx = x + directions[i].dx;
128 int dy = y + directions[i].dy;
129
130 if (map[dx][dy] == FLOOR) {
131 count++;
132 neighbor_directions[i] = 1;
133 }
134 }
135 return count;
136}
◆ generate_map()
Generate the map and populate it with keys, enemies, and the exit.
Definition at line 317 of file map_generator.c.
317 {
318
319 unsigned int seed = (unsigned int) time(NULL);
320
321 int stack_var;
322 seed ^= (uintptr_t) &stack_var;
323 srand(seed);
324
325
327
328 int start_x = 0;
329 int start_y = 0;
330 int start_edge = 0;
331 if (!exit_x && !exit_y) {
332
333
334
335 start_edge = rand() % 4;
337 } else {
339 }
340
342
344
346
348}
void initialize_map()
Initialize the map with walls.
void place_exit(int start_edge)
Place the exit on a random edge of the map, ensuring there's a path to it.
void make_exit_into_start(int *start_edge, int *start_x, int *start_y)
Set the start position on the map based on the previous exit position.
void generate_maze(int start_x, int start_y)
Generate a new maze using recursive backtracking.
void set_start_position(int start_edge, int *start_x, int *start_y)
Set the start position on the map.
void set_player_start_pos(const int player_x, const int player_y)
Sets the starting position of the player.
void populate_map()
@breif Populates the map with a key, enemies, and fountains
◆ generate_maze()
void generate_maze |
( |
int | start_x, |
|
|
int | start_y ) |
Generate a new maze using recursive backtracking.
- Parameters
-
start_x | Starting x coordinate |
start_y | Starting y coordinate |
Definition at line 228 of file map_generator.c.
228 {
229
230
231 if (start_x % 2 == 0) {
232 start_x++;
233 }
234 if (start_y % 2 == 0) {
235 start_y++;
236 }
237
238
240
241
242 int num_loops = (WIDTH * HEIGHT) / 100 + 1;
244}
void add_loops(int num_loops)
Add loops to the map by knocking down some walls.
◆ initialize_map()
Initialize the map with walls.
Definition at line 212 of file map_generator.c.
212 {
213 for (int y = 0; y < HEIGHT; y++) {
214 for (int x = 0; x < WIDTH; x++) {
215 map[x][y] = WALL;
216 revealed_map[x][y] = HIDDEN;
217 visited[x][y] = 0;
218 }
219 }
220}
◆ is_in_bounds()
int is_in_bounds |
( |
int | x, |
|
|
int | y ) |
Check if cell is within bounds of the map.
- Parameters
-
x | x coordinate of the cell |
y | y coordinate of the cell |
- Returns
- 1 if in bounds, 0 otherwise
Definition at line 47 of file map_generator.c.
47 {
48 return x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT;
49}
◆ is_valid_cell()
int is_valid_cell |
( |
int | x, |
|
|
int | y ) |
Check if a cell is a valid cell to visit (in bounds and not visited)
- Parameters
-
x | x coordinate of the cell |
y | y coordinate of the cell |
- Returns
- 1 if valid, 0 otherwise
Definition at line 57 of file map_generator.c.
57 {
59}
int is_in_bounds(int x, int y)
Check if cell is within bounds of the map.
◆ make_exit_into_start()
void make_exit_into_start |
( |
int * | start_edge, |
|
|
int * | start_x, |
|
|
int * | start_y ) |
Set the start position on the map based on the previous exit position.
- Parameters
-
start_x | pointer to the x coordinate of the start position |
start_y | pointer to the y coordinate of the start position |
Definition at line 285 of file map_generator.c.
285 {
286 switch (exit_edge) {
287 case TOP:
288 *start_edge = BOTTOM;
289 *start_x = exit_x;
290 *start_y = HEIGHT - 2;
291 map[*start_x][HEIGHT - 1] = START_DOOR;
292 break;
293 case RIGHT:
294 *start_edge = LEFT;
295 *start_x = 1;
296 *start_y = exit_y;
297 map[0][*start_y] = START_DOOR;
298 break;
299 case BOTTOM:
300 *start_edge = TOP;
301 *start_x = exit_x;
302 *start_y = 1;
303 map[*start_x][0] = START_DOOR;
304 break;
305 case LEFT:
306 *start_edge = RIGHT;
307 *start_x = WIDTH - 2;
308 *start_y = exit_y;
309 map[WIDTH - 1][*start_y] = START_DOOR;
310 break;
311 default:
312 log_msg(ERROR,
"map_generator",
"Invalid exit edge: %d", exit_edge);
313 break;
314 }
315}
void log_msg(const log_level_t level, const char *module, const char *format,...)
Logs a formatted message with a specified log level and module.
◆ place_exit()
void place_exit |
( |
int | start_edge | ) |
|
Place the exit on a random edge of the map, ensuring there's a path to it.
- Parameters
-
start_edge | the edge from which the player enters the map, the exit cannot be on this edge |
Definition at line 174 of file map_generator.c.
174 {
175
176 exit_edge = start_edge;
177 while (exit_edge == start_edge) {
178 exit_edge = rand() % 4;
179 }
180
181 do {
182 switch (exit_edge) {
183 case TOP:
184 exit_x = 1 + 2 * (rand() % ((WIDTH - 2) / 2));
185 exit_y = 0;
186 break;
187 case BOTTOM:
188 exit_x = 1 + 2 * (rand() % ((WIDTH - 2) / 2));
189 exit_y = HEIGHT - 1;
190 break;
191 case LEFT:
192 exit_x = 0;
193 exit_y = 1 + 2 * (rand() % ((HEIGHT - 2) / 2));
194 break;
195 case RIGHT:
196 exit_x = WIDTH - 1;
197 exit_y = 1 + 2 * (rand() % ((HEIGHT - 2) / 2));
198 break;
199 default:
200 log_msg(ERROR,
"map_generator",
"Invalid exit edge: %d", exit_edge);
201 return;
202 }
204
205 map[exit_x][exit_y] = EXIT_DOOR;
206}
int validate_exit_position(int exit_e, int x, int y)
Check if the exit position is adjacent to a floor cell.
◆ set_start_position()
void set_start_position |
( |
int | start_edge, |
|
|
int * | start_x, |
|
|
int * | start_y ) |
Set the start position on the map.
- Parameters
-
start_edge | the edge from which the player enters the map |
start_x | pointer to the x coordinate of the start position |
start_y | pointer to the y coordinate of the start position |
Definition at line 252 of file map_generator.c.
252 {
253 switch (start_edge) {
254 case TOP:
255 *start_x = 3 + 2 * (rand() % ((WIDTH - 5) / 2));
256 *start_y = 1;
257 map[*start_x][0] = START_DOOR;
258 break;
259 case RIGHT:
260 *start_x = WIDTH - 2;
261 *start_y = 3 + 2 * (rand() % ((HEIGHT - 5) / 2));
262 map[WIDTH - 1][*start_y] = START_DOOR;
263 break;
264 case BOTTOM:
265 *start_x = 3 + 2 * (rand() % ((WIDTH - 5) / 2));
266 *start_y = HEIGHT - 2;
267 map[*start_x][HEIGHT - 1] = START_DOOR;
268 break;
269 case LEFT:
270 *start_x = 1;
271 *start_y = 3 + 2 * (rand() % ((HEIGHT - 5) / 2));
272 map[0][*start_y] = START_DOOR;
273 break;
274 default:
275 log_msg(ERROR,
"map_generator",
"Invalid start edge: %d", start_edge);
276 break;
277 }
278}
◆ shuffle()
Shuffle array using Fisher-Yates algorithm.
This function randomly shuffles the elements of the given array of directions.
- Parameters
-
dir | Array of directions to be shuffled. |
n | Size of the array. |
Definition at line 32 of file map_generator.c.
32 {
33 for (int i = n - 1; i > 0; i--) {
34 int j = rand() % (i + 1);
36 dir[j] = dir[i];
37 dir[i] = tmp;
38 }
39}
◆ validate_exit_position()
int validate_exit_position |
( |
int | exit_e, |
|
|
int | x, |
|
|
int | y ) |
Check if the exit position is adjacent to a floor cell.
- Parameters
-
exit_e | the edge of the exit (TOP, BOTTOM, LEFT, RIGHT) |
x | x coordinate of the exit |
y | y coordinate of the exit |
- Returns
- 1 if valid, 0 otherwise
Definition at line 68 of file map_generator.c.
68 {
69 switch (exit_e) {
70 case TOP:
71 return map[x][y + 1] == FLOOR;
72 case BOTTOM:
73 return map[x][y - 1] == FLOOR;
74 case LEFT:
75 return map[x + 1][y] == FLOOR;
76 case RIGHT:
77 return map[x - 1][y] == FLOOR;
78 default:
79 log_msg(ERROR,
"map_generator",
"Invalid exit edge: %d", exit_e);
80 return 0;
81 }
82}
◆ exit_edge
◆ exit_x
◆ exit_y
◆ visited
int visited[WIDTH][HEIGHT] |