Slight better but I think place_doors can be even better.
This commit is contained in:
parent
f304538325
commit
908f5bfb3e
4 changed files with 37 additions and 36 deletions
|
|
@ -125,13 +125,12 @@ namespace maze {
|
|||
|
||||
void Builder::randomize_rooms(size_t room_size) {
|
||||
std::shuffle($dead_ends.begin(), $dead_ends.end(), Random::GENERATOR);
|
||||
|
||||
size_t max_rooms = room_sweetspot($width, room_size);
|
||||
|
||||
// use those dead ends to randomly place rooms
|
||||
for(auto at : $dead_ends) {
|
||||
// skip 50% of them
|
||||
// if(Random::uniform(0,1) == 0) continue;
|
||||
// don't bother with dead ends near the edge
|
||||
if(at.x < 2 || at.y < 2 || at.x > $width - 3 || at.y > $height - 3) continue;
|
||||
|
||||
// quit after we've hit the room max threshold
|
||||
if($rooms.size() > max_rooms) break;
|
||||
|
|
@ -242,13 +241,15 @@ namespace maze {
|
|||
void Builder::dump(const std::string& msg, bool path_too) {
|
||||
auto wall_copy = $walls;
|
||||
|
||||
// mark the rooms too
|
||||
for(auto& room : $rooms) {
|
||||
for(matrix::rectangle it{wall_copy, room.x, room.y, room.width, room.height};
|
||||
it.next();)
|
||||
{
|
||||
if(wall_copy[it.y][it.x] == 0 && wall_copy[it.y][it.x] != 3) {
|
||||
wall_copy[it.y][it.x] = ROOM_SPACE_VALUE;
|
||||
// mark the rooms too, but not if pathing
|
||||
if(!path_too) {
|
||||
for(auto& room : $rooms) {
|
||||
for(matrix::rectangle it{wall_copy, room.x, room.y, room.width, room.height};
|
||||
it.next();)
|
||||
{
|
||||
if(wall_copy[it.y][it.x] == 0) {
|
||||
wall_copy[it.y][it.x] = ROOM_SPACE_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -306,7 +307,7 @@ namespace maze {
|
|||
}
|
||||
}
|
||||
|
||||
void Builder::make_doors() {
|
||||
void Builder::place_doors() {
|
||||
for(auto room : $rooms) {
|
||||
// walk the outer wall looking for an emergent door
|
||||
int possible_doors = 0;
|
||||
|
|
@ -315,7 +316,8 @@ namespace maze {
|
|||
matrix::perimeter it{room.x - 1, room.y - 1, room.width + 2, room.height + 2};
|
||||
|
||||
while(it.next()) {
|
||||
if(matrix::inbounds($walls, it.x, it.y) && $walls[it.y][it.x] == SPACE_VALUE) {
|
||||
if(space_available(it.x, it.y)) {
|
||||
// IN_BOUNDS CHECK, or maybe a can_place or is_available?
|
||||
last_door = {it.x, it.y};
|
||||
possible_doors++;
|
||||
}
|
||||
|
|
@ -335,11 +337,12 @@ namespace maze {
|
|||
while(it.next()) {
|
||||
for(matrix::compass near_door{$walls, it.x, it.y}; near_door.next();) {
|
||||
// skip the wall parts
|
||||
if($walls[near_door.y][near_door.x] == WALL_VALUE) continue;
|
||||
if(!space_available(near_door.x, near_door.y)) continue;
|
||||
|
||||
if($ends_map.contains({near_door.x, near_door.y})) {
|
||||
if(room.contains({near_door.x, near_door.y})) {
|
||||
// last ditch effort is use the internal dead end
|
||||
// IN_BOUNDS_HERE
|
||||
last_door = {it.x, it.y};
|
||||
} else {
|
||||
$walls[it.y][it.x] = SPACE_VALUE;
|
||||
|
|
@ -406,7 +409,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(0);
|
||||
Room test_room = $rooms.at(rand(0, $rooms.size() - 1));
|
||||
Point test{test_room.x, test_room.y};
|
||||
$paths.set_target(test);
|
||||
$paths.compute_paths($walls);
|
||||
|
|
@ -423,10 +426,13 @@ namespace maze {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Builder::in_bounds(size_t x, size_t y) {
|
||||
if(x > $width) {
|
||||
|
||||
}
|
||||
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;
|
||||
dbc::check(x != $width, "bad x");
|
||||
dbc::check(y != $height, "bad y");
|
||||
return in_bounds && is_space && not_perimeter;
|
||||
}
|
||||
|
||||
void Builder::punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y) {
|
||||
|
|
@ -461,22 +467,17 @@ namespace maze {
|
|||
}
|
||||
|
||||
// now go back and see if we can add any back
|
||||
int added_back = 0;
|
||||
for(auto& at : removed_ends) {
|
||||
auto temp = $walls[at.y][at.x];
|
||||
$walls[at.y][at.x] = WALL_VALUE;
|
||||
|
||||
if(!validate()) {
|
||||
$walls[at.y][at.x] = SPACE_VALUE;
|
||||
} else {
|
||||
added_back++;
|
||||
$walls[at.y][at.x] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
enclose();
|
||||
now_valid = validate();
|
||||
|
||||
// didn't find a way to make it valid
|
||||
return now_valid;
|
||||
return validate();
|
||||
}
|
||||
|
||||
std::pair<Builder, bool> script(Map& map, nlohmann::json& config) {
|
||||
|
|
@ -498,8 +499,8 @@ namespace maze {
|
|||
} else if(aname == "open_box") {
|
||||
std::vector<int> data = action["data"];
|
||||
maze.open_box(data[0]);
|
||||
} else if(aname == "make_doors") {
|
||||
maze.make_doors();
|
||||
} else if(aname == "place_doors") {
|
||||
maze.place_doors();
|
||||
} else if(aname == "divide") {
|
||||
std::vector<size_t> data = action["data"];
|
||||
maze.divide({data[0], data[1]}, {data[2], data[3]});
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ namespace maze {
|
|||
void open_box(size_t outer_size);
|
||||
void add_dead_end(Point at);
|
||||
bool room_should_exist(Room& room, bool allow_dupes=false);
|
||||
void make_doors();
|
||||
void place_doors();
|
||||
bool validate();
|
||||
bool repair();
|
||||
void punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y);
|
||||
void in_bounds(size_t x, size_t y);
|
||||
bool space_available(size_t x, size_t y);
|
||||
};
|
||||
|
||||
std::pair<Builder, bool> script(Map& map, nlohmann::json& config);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void WorldBuilder::generate_map() {
|
|||
{"action": "clear"},
|
||||
{"action": "randomize_rooms", "data": [3]},
|
||||
{"action": "hunt_and_kill"},
|
||||
{"action": "make_doors"}
|
||||
{"action": "place_doors"}
|
||||
]
|
||||
)"_json;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ TEST_CASE("hunt-and-kill", "[mazes]") {
|
|||
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
maze.hunt_and_kill();
|
||||
maze.make_doors();
|
||||
maze.place_doors();
|
||||
REQUIRE(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("ROOM MAZE");
|
||||
|
|
@ -44,7 +44,7 @@ TEST_CASE("hunt-and-kill box", "[mazes]") {
|
|||
|
||||
maze.hunt_and_kill();
|
||||
maze.open_box(6);
|
||||
maze.make_doors();
|
||||
maze.place_doors();
|
||||
auto valid = maze.repair();
|
||||
|
||||
if(i == 41 && DUMP) {
|
||||
|
|
@ -101,7 +101,7 @@ TEST_CASE("hunt-and-kill too much", "[mazes]") {
|
|||
maze.inner_donut(9, 4);
|
||||
maze.divide({3,3}, {15,16});
|
||||
maze.hunt_and_kill();
|
||||
maze.make_doors();
|
||||
maze.place_doors();
|
||||
auto valid = maze.repair();
|
||||
|
||||
if(i == 41 && DUMP && valid) {
|
||||
|
|
@ -127,7 +127,7 @@ TEST_CASE("hunt-and-kill validator", "[mazes]") {
|
|||
maze.randomize_rooms(ROOM_SIZE);
|
||||
maze.hunt_and_kill();
|
||||
maze.open_box(6);
|
||||
maze.make_doors();
|
||||
maze.place_doors();
|
||||
valid = maze.repair();
|
||||
|
||||
if(i == 9 && DUMP) {
|
||||
|
|
@ -165,7 +165,7 @@ TEST_CASE("hunt-and-kill scripting", "[mazes]") {
|
|||
{"action": "hunt_and_kill"},
|
||||
{"action": "open_box", "data": [6]},
|
||||
{"action": "remove_dead_ends"},
|
||||
{"action": "make_doors"}
|
||||
{"action": "place_doors"}
|
||||
]
|
||||
)"_json;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue