Better map generation and a test that re-rolls maps that aren't valid to figure out the stats of map gen failures.
This commit is contained in:
parent
8090251a71
commit
f85ae8a6c6
12 changed files with 131 additions and 76 deletions
|
|
@ -6,6 +6,7 @@ namespace matrix {
|
|||
using Matrix = shiterator::Base<int>;
|
||||
|
||||
using viewport = shiterator::viewport_t<Matrix>;
|
||||
using perimeter = shiterator::perimeter_t<Matrix>;
|
||||
|
||||
using each_cell = shiterator::each_cell_t<Matrix>;
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ namespace matrix {
|
|||
using rando_rect = shiterator::rando_rect_t<Matrix>;
|
||||
using rando_rect = shiterator::rando_rect_t<Matrix>;
|
||||
using rando_box = shiterator::rando_box_t<Matrix>;
|
||||
using line = shiterator::line;
|
||||
using line = shiterator::line_t;
|
||||
|
||||
void dump(const std::string &msg, Matrix &map, int show_x=-1, int show_y=-1);
|
||||
|
||||
|
|
|
|||
|
|
@ -254,32 +254,15 @@ namespace maze {
|
|||
matrix::dump(msg, wall_copy);
|
||||
}
|
||||
|
||||
void Builder::perimeter(size_t x, size_t y, size_t width, size_t height, std::function<void(size_t x, size_t y)> cb) {
|
||||
// BUG: is the -1 on these an off-by-one
|
||||
std::array<Point, 4> starts{{
|
||||
{x,y}, {x + width-1, y}, {x + width-1, y + height-1}, {x, y + height-1}
|
||||
}};
|
||||
|
||||
std::array<Point, 4> ends{{
|
||||
{x + width-1, y}, {x + width-1, y + height-1}, {x, y + height-1}, {x,y},
|
||||
}};
|
||||
|
||||
for(size_t i = 0; i < starts.size(); i++) {
|
||||
for(matrix::line it{starts[i], ends[i]}; it.next();) {
|
||||
cb(it.x, it.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::enclose() {
|
||||
size_t width = matrix::width($walls);
|
||||
size_t height = matrix::height($walls);
|
||||
|
||||
perimeter(0, 0, width, height, [&](size_t x, size_t y) {
|
||||
$walls[y][x] = WALL_VALUE;
|
||||
Point at{x,y};
|
||||
for(matrix::perimeter it{0, 0, width, height}; it.next();) {
|
||||
$walls[it.y][it.x] = WALL_VALUE;
|
||||
Point at{it.x,it.y};
|
||||
if($doors.contains(at)) $doors.erase(at);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::open_box(size_t outer_size) {
|
||||
|
|
@ -296,46 +279,66 @@ namespace maze {
|
|||
size_t width = (outer_size * 2) + 1;
|
||||
size_t height = (outer_size * 2) + 1;
|
||||
|
||||
perimeter(x, y, width, height, [&](size_t x, size_t y) {
|
||||
for(matrix::compass it{$walls, x, y}; it.next();) {
|
||||
for(matrix::perimeter p{x, y, width, height}; p.next();) {
|
||||
for(matrix::compass it{$walls, p.x, p.y}; it.next();) {
|
||||
if($ends_map.contains({it.x, it.y})) {
|
||||
$walls[y][x] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::make_doors() {
|
||||
for(auto room : $rooms) {
|
||||
// walk the outer wall looking for an emergent door
|
||||
int has_door = 0;
|
||||
int possible_doors = 0;
|
||||
Point last_door{0,0};
|
||||
|
||||
perimeter(room.x - 1, room.y - 1, room.width + 2, room.height + 2, [&](size_t x, size_t y) {
|
||||
if($walls[y][x] == SPACE_VALUE) {
|
||||
last_door = {x, y};
|
||||
has_door++;
|
||||
}
|
||||
});
|
||||
matrix::perimeter it{room.x - 1, room.y - 1, room.width + 2, room.height + 2};
|
||||
|
||||
// if only found one then make that an actual door
|
||||
if(has_door == 1) {
|
||||
$doors.insert_or_assign(last_door, true);
|
||||
while(it.next()) {
|
||||
if($walls[it.y][it.x] == SPACE_VALUE) {
|
||||
last_door = {it.x, it.y};
|
||||
possible_doors++;
|
||||
}
|
||||
}
|
||||
|
||||
// no emergent door found, punch out one
|
||||
perimeter(room.x, room.y, room.width, room.height, [&](size_t x, size_t 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;
|
||||
$doors.insert_or_assign({size_t(door_at.x), size_t(door_at.y)}, true);
|
||||
// if only found one then make that an actual door
|
||||
if(possible_doors == 1) {
|
||||
$doors.insert_or_assign(last_door, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// no natural door found, need to make one
|
||||
it = {room.x - 1, room.y - 1, room.width + 2, room.height + 2};
|
||||
last_door = {0,0};
|
||||
bool found_door = false;
|
||||
|
||||
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($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
|
||||
last_door = {it.x, it.y};
|
||||
} else {
|
||||
$walls[it.y][it.x] = SPACE_VALUE;
|
||||
$doors.insert_or_assign({it.x, it.y}, true);
|
||||
found_door = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(!found_door && last_door.x != 0) {
|
||||
// didn't find an external door so punch one at the dead end
|
||||
$walls[last_door.y][last_door.x] = SPACE_VALUE;
|
||||
$doors.insert_or_assign({last_door.x, last_door.y}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -376,14 +379,10 @@ namespace maze {
|
|||
if(!room_should_exist(room)) return false;
|
||||
}
|
||||
|
||||
bool bad_perimeter = false;
|
||||
// BUG: this is dogshit, get rid of perimeter, I can't even spell it right it's so bad
|
||||
perimeter(0, 0, width, height, [&](size_t x, size_t y) {
|
||||
if($ends_map.contains({x, y})) bad_perimeter = true;
|
||||
if($doors.contains({x, y})) bad_perimeter = true;
|
||||
});
|
||||
|
||||
if(bad_perimeter) return false;
|
||||
for(matrix::perimeter it{0, 0, width, height}; it.next();) {
|
||||
if($ends_map.contains({it.x, it.y})) return false;
|
||||
if($doors.contains({it.x, it.y})) return false;
|
||||
}
|
||||
|
||||
if($rooms.size() == 1) return true;
|
||||
|
||||
|
|
@ -393,7 +392,7 @@ namespace maze {
|
|||
Point test{test_room.x, test_room.y};
|
||||
$paths.set_target(test);
|
||||
$paths.compute_paths($walls);
|
||||
$paths.dump("AFTER COMPUTE");
|
||||
// $paths.dump("AFTER COMPUTE");
|
||||
$paths.clear_target(test);
|
||||
|
||||
for(matrix::each_cell it{$walls}; it.next();) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ namespace maze {
|
|||
void divide(Point start, Point end);
|
||||
void remove_dead_ends();
|
||||
void dump(const std::string& msg);
|
||||
void perimeter(size_t x, size_t y, size_t width, size_t height, std::function<void(size_t x, size_t y)> cb);
|
||||
void open_box(size_t outer_size);
|
||||
void add_dead_end(Point at);
|
||||
bool room_should_exist(Room& room, bool allow_dupes=false);
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ namespace shiterator {
|
|||
* within your Matrix, as it's assumed _you_ did that
|
||||
* already.
|
||||
*/
|
||||
struct line {
|
||||
struct line_t {
|
||||
int x;
|
||||
int y;
|
||||
int x1;
|
||||
|
|
@ -407,7 +407,7 @@ namespace shiterator {
|
|||
int dy;
|
||||
int error;
|
||||
|
||||
line(Point start, Point end) :
|
||||
line_t(Point start, Point end) :
|
||||
x(start.x), y(start.y),
|
||||
x1(end.x), y1(end.y)
|
||||
{
|
||||
|
|
@ -594,6 +594,46 @@ namespace shiterator {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename MAT>
|
||||
struct perimeter_t {
|
||||
size_t x;
|
||||
size_t y;
|
||||
size_t width;
|
||||
size_t height;
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
std::array<Point, 4> starts{{
|
||||
{x,y}, {x + width-1, y}, {x + width-1, y + height-1}, {x, y + height-1}
|
||||
}};
|
||||
|
||||
std::array<Point, 4> ends{{
|
||||
{x + width-1, y}, {x + width-1, y + height-1}, {x, y + height-1}, {x,y},
|
||||
}};
|
||||
|
||||
line_t it{starts[i], ends[i]};
|
||||
|
||||
bool next() {
|
||||
if(i >= starts.size()) return false;
|
||||
|
||||
if(it.next()) {
|
||||
x = it.x;
|
||||
y = it.y;
|
||||
return true;
|
||||
} else {
|
||||
x = 0;
|
||||
y = 0;
|
||||
i++;
|
||||
if(i < starts.size()) {
|
||||
it = {starts[i], ends[i]};
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* BROKEN: I'm actually not sure what I'm trying to
|
||||
* do here yet.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include "game/config.hpp"
|
||||
#include "graphics/palette.hpp"
|
||||
|
||||
namespace sfml {
|
||||
namespace gui {
|
||||
using namespace nlohmann;
|
||||
|
||||
guecs::SpriteTexture Backend::get_sprite(const string& name) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "guecs/ui.hpp"
|
||||
|
||||
namespace sfml {
|
||||
namespace gui {
|
||||
using std::string;
|
||||
|
||||
class Backend : public guecs::Backend {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
int main(int argc, char* argv[]) {
|
||||
try {
|
||||
sfml::Backend backend;
|
||||
gui::Backend backend;
|
||||
|
||||
shaders::init();
|
||||
components::init();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue