More cleanups of the tests and fixes to the room and door positioning.

This commit is contained in:
Zed A. Shaw 2026-03-15 22:53:00 -04:00
parent 8e2a691337
commit 02d23bb77d
11 changed files with 75 additions and 78 deletions

View file

@ -9,16 +9,6 @@ using std::string;
using matrix::Matrix;
namespace maze {
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 complete(Matrix& maze, size_t width, size_t height) {
for(size_t row = 1; row < height; row += 2) {
for(size_t col = 1; col < width; col += 2) {
@ -89,8 +79,9 @@ namespace maze {
}
bool Builder::room_should_exist(Room& room, bool allow_dupes) {
if(!matrix::inbounds($walls, room.x, room.y) ||
!matrix::inbounds($walls, room.x + room.width, room.y + room.height))
// padding by 1 for the perimeter wall
if(!matrix::inbounds($walls, room.x - 1, room.y - 1) ||
!matrix::inbounds($walls, room.x + room.width + 2, room.y + room.height + 2))
{
return false;
}
@ -187,7 +178,7 @@ namespace maze {
$walls[row][col] = 0;
} else {
// found neighbors, pick random one
auto nb = n[rand(size_t(0), n.size() - 1)];
auto nb = n[Random::abs(size_t(0), n.size() - 1)];
$walls[nb.y][nb.x] = 0;
size_t row = (nb.y + on.y) / 2;
@ -196,12 +187,14 @@ namespace maze {
on = nb;
}
}
if($rooms.size() > 0) place_rooms();
}
void Builder::place_rooms() {
for(auto& room : $rooms) {
for(matrix::rectangle it{$walls, room.x, room.y, room.width, room.height}; it.next();) {
$walls[it.y][it.x] = 0;
$walls[it.y][it.x] = SPACE_VALUE;
}
}
}
@ -239,7 +232,7 @@ namespace maze {
}
void Builder::dump(const std::string& msg, bool path_too) {
auto wall_copy = $walls;
Matrix wall_copy = $walls;
// mark the rooms too, but not if pathing
if(!path_too) {
@ -307,6 +300,11 @@ namespace maze {
}
}
bool Builder::valid_door(size_t x, size_t y) {
return (space_available(x, y - 1) && space_available(x, y + 1)) // north south
|| (space_available(x - 1, y) && space_available(x + 1, y));
}
void Builder::place_doors() {
for(auto room : $rooms) {
int best_longest = 0;
@ -319,17 +317,14 @@ namespace maze {
// can't path out of the room, so now punch a hole until it can
matrix::perimeter it{room.x - 1, room.y - 1, room.width + 2, room.height + 2};
while(it.next()) {
// don't use corners
if((it.x == room.x - 1 && it.y == room.y - 1) ||
(it.x == room.x - 1 && it.y == room.y + 2) ||
(it.x == room.width + 2 && it.y == room.y + 2) ||
(it.x == room.width + 2 && it.y == room.y - 1)) {
continue;
}
while(it.next()) {
if($walls[it.y][it.x] == WALL_VALUE) {
// valid doors are free north/south or east/west
if(!valid_door(it.x, it.y)) continue;
$walls[it.y][it.x] = SPACE_VALUE;
longest = compute_paths(room.x, room.y);
// keep track of the best door so far, which is the one with the longest path
@ -348,8 +343,6 @@ namespace maze {
$walls[best_door.y][best_door.x] = SPACE_VALUE;
$doors.insert_or_assign(best_door, true);
}
fmt::println("map valid after doors? {}", validate());
}
void Builder::inner_box(size_t outer_size, size_t inner_size) {
@ -408,7 +401,7 @@ namespace maze {
// initial path test can just use one room then look for
// any cells that are empty in the walls map but unpathed in the paths
Room test_room = $rooms.at(rand(0, $rooms.size() - 1));
Room test_room = $rooms.at(Random::abs(size_t(0), $rooms.size() - 1));
compute_paths(test_room.x, test_room.y);
for(matrix::each_cell it{$walls}; it.next();) {
@ -422,10 +415,10 @@ namespace maze {
}
bool Builder::space_available(size_t x, size_t y) {
bool in_bounds = matrix::inbounds($walls, x, y);
bool is_space = $walls[y][x] == SPACE_VALUE;
bool not_perimeter = x > 0 && y > 0 && x < $width - 2 && y < $height - 2;
return in_bounds && is_space && not_perimeter;
return (matrix::inbounds($walls, x, y) && // in bounds
$walls[y][x] == SPACE_VALUE && // is a space
!$doors.contains({x, y}) && // no door there
(x > 0 && y > 0 && x < $width - 2 && y < $height - 2)); // not perimeter;
}
void Builder::punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y) {

View file

@ -47,6 +47,7 @@ namespace maze {
void punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y);
bool space_available(size_t x, size_t y);
int compute_paths(size_t x, size_t y);
bool valid_door(size_t x, size_t y);
};
std::pair<Builder, bool> script(Map& map, nlohmann::json& config);

View file

@ -9,5 +9,4 @@ namespace Random {
int tick = Random::uniform_real(float(from), float(to));
return std::chrono::milliseconds{tick};
}
}

View file

@ -27,5 +27,15 @@ namespace Random {
return rand(GENERATOR);
}
auto abs(auto i, auto j) {
if(i < j) {
return Random::uniform(i, j);
} else if(j < i) {
return Random::uniform(j, i);
} else {
return i;
}
}
std::chrono::milliseconds milliseconds(int from, int to);
}