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);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue