More refinement of the maps. Now the inner box won't have rooms in it and I can mark a region free of rooms. Rooms also have a guaranteed door.
This commit is contained in:
parent
87a1193a4a
commit
8b129aea6b
4 changed files with 40 additions and 33 deletions
|
|
@ -101,6 +101,10 @@ namespace maze {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(room.overlaps($no_rooms_region)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for(auto& other : $rooms) {
|
for(auto& other : $rooms) {
|
||||||
if(room.overlaps(other)) return false;
|
if(room.overlaps(other)) return false;
|
||||||
}
|
}
|
||||||
|
|
@ -113,8 +117,7 @@ namespace maze {
|
||||||
// use those dead ends to randomly place rooms
|
// use those dead ends to randomly place rooms
|
||||||
for(auto at : $dead_ends) {
|
for(auto at : $dead_ends) {
|
||||||
// moving by +1 can randomly surround rooms with walls or not
|
// moving by +1 can randomly surround rooms with walls or not
|
||||||
size_t offset = Random::uniform(0,1);
|
Room cur{at.x, at.y, room_size, room_size};
|
||||||
Room cur{at.x+offset, at.y+offset, room_size, room_size};
|
|
||||||
bool selected = Random::uniform(0,1) == 0;
|
bool selected = Random::uniform(0,1) == 0;
|
||||||
|
|
||||||
// if it's out of bounds skip it
|
// if it's out of bounds skip it
|
||||||
|
|
@ -184,16 +187,14 @@ namespace maze {
|
||||||
size_t x = matrix::width($walls) / 2;
|
size_t x = matrix::width($walls) / 2;
|
||||||
size_t y = matrix::height($walls) / 2;
|
size_t y = matrix::height($walls) / 2;
|
||||||
|
|
||||||
for(matrix::circle it{$walls, {x, y}, outer_rad};
|
for(matrix::circle it{$walls, {x, y}, outer_rad}; it.next();)
|
||||||
it.next();)
|
|
||||||
{
|
{
|
||||||
for(int x = it.left; x < it.right; x++) {
|
for(int x = it.left; x < it.right; x++) {
|
||||||
$walls[it.y][x] = 0;
|
$walls[it.y][x] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(matrix::circle it{$walls, {x, y}, inner_rad};
|
for(matrix::circle it{$walls, {x, y}, inner_rad}; it.next();)
|
||||||
it.next();)
|
|
||||||
{
|
{
|
||||||
for(int x = it.left; x < it.right; x++) {
|
for(int x = it.left; x < it.right; x++) {
|
||||||
$walls[it.y][x] = 1;
|
$walls[it.y][x] = 1;
|
||||||
|
|
@ -288,6 +289,23 @@ namespace maze {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Builder::make_doors() {
|
||||||
|
for(auto room : $rooms) {
|
||||||
|
perimeter(room.x, room.y, room.width, room.height, [&](auto x, auto y) {
|
||||||
|
if($ends_map.contains({x, y})) {
|
||||||
|
for(matrix::compass door_at{$walls, x, y}; door_at.next();) {
|
||||||
|
if($walls[door_at.y][door_at.x] == WALL_VALUE) {
|
||||||
|
$walls[door_at.y][door_at.x] = SPACE_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
enclose();
|
||||||
|
}
|
||||||
|
|
||||||
void Builder::inner_box(size_t outer_size, size_t inner_size) {
|
void Builder::inner_box(size_t outer_size, size_t inner_size) {
|
||||||
size_t x = matrix::width($walls) / 2;
|
size_t x = matrix::width($walls) / 2;
|
||||||
size_t y = matrix::height($walls) / 2;
|
size_t y = matrix::height($walls) / 2;
|
||||||
|
|
@ -301,6 +319,9 @@ namespace maze {
|
||||||
{
|
{
|
||||||
$walls[it.y][it.x] = 1;
|
$walls[it.y][it.x] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make a fake room that blocks others
|
||||||
|
$no_rooms_region = {x - outer_size, y - outer_size, outer_size * 2 + 1, outer_size * 2 + 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::add_dead_end(Point at) {
|
void Builder::add_dead_end(Point at) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ namespace maze {
|
||||||
std::vector<Room>& $rooms;
|
std::vector<Room>& $rooms;
|
||||||
std::vector<Point>& $dead_ends;
|
std::vector<Point>& $dead_ends;
|
||||||
std::unordered_map<Point, bool> $ends_map;
|
std::unordered_map<Point, bool> $ends_map;
|
||||||
|
Room $no_rooms_region{0,0,0,0};
|
||||||
|
|
||||||
Builder(Map& map) :
|
Builder(Map& map) :
|
||||||
$walls(map.$walls), $rooms(map.$rooms), $dead_ends(map.$dead_ends)
|
$walls(map.$walls), $rooms(map.$rooms), $dead_ends(map.$dead_ends)
|
||||||
|
|
@ -32,5 +33,6 @@ namespace maze {
|
||||||
void open_box(size_t outer_size);
|
void open_box(size_t outer_size);
|
||||||
void add_dead_end(Point at);
|
void add_dead_end(Point at);
|
||||||
bool room_should_exist(Room& room);
|
bool room_should_exist(Room& room);
|
||||||
|
void make_doors();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,25 +14,6 @@
|
||||||
using lighting::LightSource;
|
using lighting::LightSource;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct Point {
|
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rect {
|
|
||||||
Point p1, p2, p3, p4;
|
|
||||||
// four corners (any order)
|
|
||||||
bool contains(const Point& pt) const {
|
|
||||||
double minX = std::min({p1.x, p2.x, p3.x, p4.x});
|
|
||||||
double maxX = std::max({p1.x, p2.x, p3.x, p4.x});
|
|
||||||
double minY = std::min({p1.y, p2.y, p3.y, p4.y});
|
|
||||||
double maxY = std::max({p1.y, p2.y, p3.y, p4.y});
|
|
||||||
return pt.x >= minX && pt.x <= maxX && pt.y >= minY && pt.y <= maxY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct Room {
|
struct Room {
|
||||||
size_t x = 0;
|
size_t x = 0;
|
||||||
size_t y = 0;
|
size_t y = 0;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ TEST_CASE("hunt-and-kill", "[mazes]") {
|
||||||
|
|
||||||
maze.randomize_rooms(ROOM_SIZE);
|
maze.randomize_rooms(ROOM_SIZE);
|
||||||
maze.hunt_and_kill();
|
maze.hunt_and_kill();
|
||||||
|
maze.make_doors();
|
||||||
// maze.dump("ROOM MAZE");
|
// maze.dump("ROOM MAZE");
|
||||||
|
|
||||||
REQUIRE(map.$dead_ends.size() > 0);
|
REQUIRE(map.$dead_ends.size() > 0);
|
||||||
|
|
@ -30,15 +31,16 @@ TEST_CASE("hunt-and-kill box", "[mazes]") {
|
||||||
maze::Builder maze(map);
|
maze::Builder maze(map);
|
||||||
|
|
||||||
maze.hunt_and_kill();
|
maze.hunt_and_kill();
|
||||||
maze.randomize_rooms(ROOM_SIZE+1);
|
|
||||||
maze.clear();
|
maze.clear();
|
||||||
|
maze.inner_box(6, 4);
|
||||||
|
maze.randomize_rooms(ROOM_SIZE+2);
|
||||||
|
|
||||||
maze.inner_box(6, 3);
|
|
||||||
maze.hunt_and_kill();
|
maze.hunt_and_kill();
|
||||||
maze.open_box(6);
|
maze.open_box(6);
|
||||||
|
maze.make_doors();
|
||||||
|
|
||||||
if(maze.$rooms.size() == 0) {
|
if(i == 42) {
|
||||||
maze.dump("NO ROOMS");
|
maze.dump("INNER BOX");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,8 +69,6 @@ TEST_CASE("hunt-and-kill fissure", "[mazes]") {
|
||||||
REQUIRE(maze.$rooms.size() == 0);
|
REQUIRE(maze.$rooms.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("hunt-and-kill no-dead-ends", "[mazes]") {
|
TEST_CASE("hunt-and-kill no-dead-ends", "[mazes]") {
|
||||||
Map map(21, 21);
|
Map map(21, 21);
|
||||||
maze::Builder maze(map);
|
maze::Builder maze(map);
|
||||||
|
|
@ -88,10 +88,13 @@ TEST_CASE("hunt-and-kill too much", "[mazes]") {
|
||||||
maze.hunt_and_kill();
|
maze.hunt_and_kill();
|
||||||
maze.randomize_rooms(ROOM_SIZE);
|
maze.randomize_rooms(ROOM_SIZE);
|
||||||
maze.clear();
|
maze.clear();
|
||||||
maze.inner_donut(4, 2);
|
maze.inner_donut(9, 4);
|
||||||
maze.divide({3,3}, {15,16});
|
maze.divide({3,3}, {15,16});
|
||||||
maze.hunt_and_kill();
|
maze.hunt_and_kill();
|
||||||
|
maze.make_doors();
|
||||||
|
|
||||||
// maze.dump("COMBINED");
|
// if(i == 41) {
|
||||||
|
// maze.dump("COMBINED");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue