You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.2 KiB
145 lines
3.2 KiB
#include <fmt/core.h>
|
|
#include <string>
|
|
#include "rand.hpp"
|
|
#include "constants.hpp"
|
|
#include "maze.hpp"
|
|
|
|
using std::string;
|
|
using matrix::Matrix;
|
|
|
|
inline size_t rand(size_t i, size_t j) {
|
|
if(i < j) {
|
|
return Random::uniform(i, j);
|
|
} else if(j < i) {
|
|
return Random::uniform(j, i);
|
|
} else {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
|
|
inline bool split_dir(size_t iDim, size_t jDim) {
|
|
if(iDim < jDim) {
|
|
return false;
|
|
} else if(jDim < iDim) {
|
|
return true;
|
|
} else {
|
|
return Random::uniform(0, 1);
|
|
}
|
|
}
|
|
|
|
inline bool good_hole(Matrix &map, size_t split, size_t hole, bool horiz) {
|
|
if(hole % 2 == 0) return false;
|
|
|
|
size_t j = horiz ? split : hole;
|
|
size_t i = horiz ? hole : split;
|
|
if(map[j][i] == WALL_PATH_LIMIT) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void divide(Matrix& map, std::vector<Room> &rooms,
|
|
Point iCoords, Point jCoords, bool horizontal) {
|
|
int iDim = iCoords.y - iCoords.x;
|
|
int jDim = jCoords.y - jCoords.x;
|
|
bool punch_room = false;
|
|
|
|
if(iDim <= 0 || jDim <= 0) {
|
|
return;
|
|
} else if(iDim <= 2 && jDim <= 2) {
|
|
fmt::println("MADE ROOM! {},{}; {},{}",
|
|
iCoords.x, iCoords.y, jCoords.x, jCoords.y);
|
|
punch_room = true;
|
|
}
|
|
|
|
if(horizontal) {
|
|
size_t split = 0;
|
|
do {
|
|
split = rand(iCoords.x, iCoords.x + iDim + 1);
|
|
} while(split % 2);
|
|
|
|
size_t hole = 0;
|
|
do {
|
|
hole = rand(jCoords.x, jCoords.x + jDim +1);
|
|
} while(good_hole(map, split, hole, horizontal));
|
|
|
|
for(size_t j = jCoords.x; j <= jCoords.y; j++) {
|
|
if(j != hole) {
|
|
map[split][j] = WALL_PATH_LIMIT;
|
|
}
|
|
}
|
|
|
|
divide(map, rooms,
|
|
{iCoords.x, size_t(split - 1)},
|
|
jCoords,
|
|
split_dir(split - iCoords.x - 1, jDim));
|
|
|
|
divide(map, rooms,
|
|
{size_t(split + 1), iCoords.y},
|
|
jCoords,
|
|
split_dir(iCoords.x - split - 1, jDim));
|
|
} else {
|
|
size_t split = 0;
|
|
do {
|
|
split = rand(jCoords.x, jCoords.x + jDim + 1);
|
|
} while(split % 2);
|
|
|
|
size_t hole = 0;
|
|
do {
|
|
hole = rand(iCoords.x, iCoords.x + iDim + 1);
|
|
} while(good_hole(map, split, hole, horizontal));
|
|
|
|
for(size_t i = iCoords.x; i <= iCoords.y; i++) {
|
|
if(i != hole) {
|
|
map[i][split] = WALL_PATH_LIMIT;
|
|
}
|
|
}
|
|
|
|
divide(map, rooms,
|
|
iCoords,
|
|
{jCoords.x, size_t(split - 1)},
|
|
split_dir(iDim, split - jCoords.x - 1));
|
|
|
|
divide(map, rooms,
|
|
iCoords,
|
|
{size_t(split + 1), jCoords.y},
|
|
Random::uniform(0, 1));
|
|
}
|
|
|
|
if(punch_room) {
|
|
for(size_t j = jCoords.x; j <= jCoords.y; j++) {
|
|
for(size_t i = iCoords.x; i <= iCoords.y; i++) {
|
|
map[j][i] = 0;
|
|
}
|
|
}
|
|
|
|
Room room{iCoords.x, jCoords.x, iCoords.y - iCoords.x + 1, jCoords.y - jCoords.x + 1};
|
|
|
|
for(auto r : rooms) {
|
|
if(r.x == room.x && r.y == room.y) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
rooms.push_back(room);
|
|
}
|
|
}
|
|
|
|
|
|
void maze::recursive_div(Matrix& map, std::vector<Room>& rooms) {
|
|
size_t width = matrix::width(map);
|
|
size_t height = matrix::height(map);
|
|
|
|
for(size_t i = 0; i < height; i++) {
|
|
for(size_t j = 0; j < width; j++) {
|
|
int val = (i == 0 ||
|
|
j == 0 ||
|
|
i == height - 1 ||
|
|
j == width - 1);
|
|
|
|
map[i][j] = val == 1 ? WALL_PATH_LIMIT : 0;
|
|
}
|
|
}
|
|
|
|
divide(map, rooms, {1, height - 2}, {1, width - 2}, split_dir(1, 1));
|
|
}
|
|
|