/* This file is part of urlg. urlg is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. urlg is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar. If not, see . */ #include "cavegen.h" #include #include #include #define MAX_STEPS 200 #define NUM_WALKERS 100 enum direction { UP, LEFT, RIGHT, DOWN, NUM_DIRS, }; void create_cave(struct map *map) { map->width = WIDTH; map->height = HEIGHT; // create a map consisting entirely of walls map->map = malloc(sizeof(enum tile_type) * HEIGHT * WIDTH); for (int i = 0; i < HEIGHT; ++i) { for (int j = 0; j < WIDTH; ++j) { map->map[i * WIDTH + j] = WALL; } } // start in the middle of the screen int start_x = WIDTH / 2; int start_y = HEIGHT / 2; // make the starting point GROUND map->map[start_y * WIDTH + start_x] = GROUND; // setup the open tiles struct point *open_tiles = malloc(sizeof(struct point) * HEIGHT * WIDTH); int num_open_tiles = 1; open_tiles[0].x = start_x; open_tiles[0].y = start_y; for (int i = 0; i < NUM_WALKERS; ++i) { // get a random open point struct point curr_point = open_tiles[rand() % num_open_tiles]; int x_pos = curr_point.x; int y_pos = curr_point.y; // iterate until the walk exits the array or MAX_STEPS is reached for (int j = 1; j < MAX_STEPS - 1 && x_pos < WIDTH - 1 && x_pos >= 1 && y_pos < HEIGHT - 1 && y_pos >= 1; ++j) { // add new open point if the current point is still a wall if (map->map[y_pos * WIDTH + x_pos] == WALL) { open_tiles[num_open_tiles].x = x_pos; open_tiles[num_open_tiles].y = y_pos; ++num_open_tiles; } map->map[y_pos * WIDTH + x_pos] = GROUND; // assign ground // move in a random direction enum direction dir = rand() % NUM_DIRS; switch (dir) { case UP : --y_pos; break; case LEFT : --x_pos; break; case RIGHT : ++x_pos; break; case DOWN : ++y_pos; break; default : exit(EXIT_FAILURE); // should not occur } } } // assign the up stair and remove from open tiles int in = rand() % num_open_tiles; map->entry_point = open_tiles[in]; open_tiles[in] = open_tiles[num_open_tiles - 1]; --num_open_tiles; map->map[map->entry_point.y * WIDTH + map->entry_point.x] = UP_STAIR; // assign the down stair and remove from open tiles in = rand() % num_open_tiles; struct point down = open_tiles[in]; open_tiles[in] = open_tiles[num_open_tiles - 1]; --num_open_tiles; map->map[down.y * WIDTH + down.x] = DOWN_STAIR; free(open_tiles); }