Maze gen can now more efficiently produce an interesting map that is fully pathable.
This commit is contained in:
parent
f85ae8a6c6
commit
e6fcbd8dcf
3 changed files with 75 additions and 8 deletions
|
|
@ -215,12 +215,11 @@ namespace maze {
|
|||
|
||||
void Builder::remove_dead_ends() {
|
||||
dbc::check($dead_ends.size() > 0, "you have to run an algo first, no dead_ends to remove");
|
||||
|
||||
for(auto at : $dead_ends) {
|
||||
for(matrix::compass it{$walls, at.x, at.y}; it.next();) {
|
||||
if($walls[it.y][it.x] == 0) {
|
||||
int diff_x = at.x - it.x;
|
||||
int diff_y = at.y - it.y;
|
||||
$walls[at.y + diff_y][at.x + diff_x] = 0;
|
||||
if($walls[it.y][it.x] == SPACE_VALUE) {
|
||||
punch_dead_end(at.x, at.y, it.x, it.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -404,4 +403,62 @@ namespace maze {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Builder::punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y) {
|
||||
int diff_x = at_x - x;
|
||||
int diff_y = at_y - y;
|
||||
$walls[at_y + diff_y][at_x + diff_x] = SPACE_VALUE;
|
||||
}
|
||||
|
||||
bool Builder::repair() {
|
||||
// possible fixes
|
||||
// go through each dead end and remove until it works
|
||||
// go through each room and add a door until it works
|
||||
// only find rooms that are unpathable and fix them
|
||||
// walk the path deleting dead ends at the end of the path
|
||||
std::vector<Point> removed_ends;
|
||||
bool now_valid = false;
|
||||
|
||||
for(auto& at : $dead_ends) {
|
||||
// punch a hole for this dead end
|
||||
for(matrix::compass it{$walls, at.x, at.y}; it.next();) {
|
||||
if($walls[it.y][it.x] == SPACE_VALUE) {
|
||||
punch_dead_end(at.x, at.y, it.x, it.y);
|
||||
removed_ends.push_back({it.x, it.y});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if that validates it then done
|
||||
if(validate()) {
|
||||
now_valid = true;
|
||||
fmt::println("MID dead_end removed={}, total={}, %={}",
|
||||
removed_ends.size(), $dead_ends.size(),
|
||||
float(removed_ends.size()) / float($dead_ends.size()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now go back and see if we can add any back
|
||||
int added_back = 0;
|
||||
for(auto& at : removed_ends) {
|
||||
$walls[at.y][at.x] = WALL_VALUE;
|
||||
|
||||
if(!validate()) {
|
||||
$walls[at.y][at.x] = SPACE_VALUE;
|
||||
} else {
|
||||
added_back++;
|
||||
}
|
||||
}
|
||||
|
||||
enclose();
|
||||
now_valid = validate();
|
||||
|
||||
fmt::println("FINAL now_valid={} added_back={} removed={}, total={}, %={}",
|
||||
now_valid, added_back, removed_ends.size() - added_back, $dead_ends.size(),
|
||||
float(removed_ends.size() - added_back) / float($dead_ends.size()));
|
||||
|
||||
// didn't find a way to make it valid
|
||||
return now_valid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,5 +40,7 @@ namespace maze {
|
|||
bool room_should_exist(Room& room, bool allow_dupes=false);
|
||||
void make_doors();
|
||||
bool validate();
|
||||
bool repair();
|
||||
void punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "algos/maze.hpp"
|
||||
#include "algos/stats.hpp"
|
||||
|
||||
#define DUMP 1
|
||||
#define DUMP 0
|
||||
|
||||
using std::string;
|
||||
using matrix::Matrix;
|
||||
|
|
@ -106,7 +106,7 @@ TEST_CASE("hunt-and-kill validator", "[mazes]") {
|
|||
bool valid = true;
|
||||
Stats mofm;
|
||||
|
||||
for(int i = 0; i < 100; i++) {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
Stats door_prob;
|
||||
|
||||
do {
|
||||
|
|
@ -123,16 +123,24 @@ TEST_CASE("hunt-and-kill validator", "[mazes]") {
|
|||
maze.enclose();
|
||||
|
||||
valid = maze.validate();
|
||||
if(valid && i == 99) {
|
||||
maze.dump("VALIDATED");
|
||||
if(!valid) valid = maze.repair();
|
||||
|
||||
if(i == 9) {
|
||||
if(valid) {
|
||||
maze.dump("VALIDATED");
|
||||
} else {
|
||||
matrix::dump("PATHING", maze.$paths.$paths);
|
||||
}
|
||||
}
|
||||
|
||||
door_prob.sample(valid);
|
||||
} while(!valid);
|
||||
|
||||
door_prob.dump();
|
||||
mofm.sample(door_prob.mean());
|
||||
}
|
||||
|
||||
fmt::println("FINAL m-of-m");
|
||||
mofm.dump();
|
||||
REQUIRE(mofm.mean() > 0.20);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue