Playing with maze gen again.
This commit is contained in:
parent
c97648ab3a
commit
33cd490ed3
8 changed files with 164 additions and 36 deletions
4
Makefile
4
Makefile
|
@ -26,7 +26,7 @@ tracy_build:
|
|||
meson compile -j 10 -C builddir
|
||||
|
||||
test: build
|
||||
./builddir/runtests
|
||||
./builddir/runtests "[mazes]"
|
||||
|
||||
run: build test
|
||||
ifeq '$(OS)' 'Windows_NT'
|
||||
|
@ -49,7 +49,7 @@ clean:
|
|||
meson compile --clean -C builddir
|
||||
|
||||
debug_test: build
|
||||
gdb --nx -x .gdbinit --ex run --args builddir/runtests -e
|
||||
gdb --nx -x .gdbinit --ex run --args builddir/runtests -e "[mazes]"
|
||||
|
||||
win_installer:
|
||||
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'
|
||||
|
|
|
@ -100,6 +100,11 @@
|
|||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"lava_floor":
|
||||
{"path": "assets/lava_floor-256.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"ceiling":
|
||||
{"path": "assets/ceiling_test-256.png",
|
||||
"frame_width": 256,
|
||||
|
|
BIN
assets/lava_floor-256.png
Normal file
BIN
assets/lava_floor-256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 137 KiB |
15
map.cpp
15
map.cpp
|
@ -165,21 +165,6 @@ void Map::expand() {
|
|||
}
|
||||
|
||||
void Map::add_room(Room &room) {
|
||||
room.x++;
|
||||
room.y++;
|
||||
room.width--;
|
||||
room.height--;
|
||||
|
||||
if(room.x + room.width >= $width) {
|
||||
// fix the width
|
||||
room.x--;
|
||||
}
|
||||
|
||||
if(room.y + room.height >= $height) {
|
||||
// fix the height
|
||||
room.y--;
|
||||
}
|
||||
|
||||
$rooms.push_back(room);
|
||||
}
|
||||
|
||||
|
|
64
maze.cpp
64
maze.cpp
|
@ -93,16 +93,39 @@ inline std::pair<Point, Point> find_coord(Matrix& maze) {
|
|||
dbc::sentinel("failed to find coord?");
|
||||
}
|
||||
|
||||
void maze::hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Point>& dead_ends) {
|
||||
void maze::randomize_rooms(std::vector<Room>& rooms_out, std::vector<Point> maybe_here) {
|
||||
dbc::check(maybe_here.size() >= 2, "must have at least two possible points to place rooms");
|
||||
|
||||
while(rooms_out.size() < 2) {
|
||||
// use those dead ends to randomly place rooms
|
||||
for(auto at : maybe_here) {
|
||||
if(Random::uniform(0,1)) {
|
||||
size_t offset = Random::uniform(0,1);
|
||||
Room cur{at.x+offset, at.y+offset, 1, 1};
|
||||
rooms_out.push_back(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void maze::init(Matrix& maze) {
|
||||
matrix::assign(maze, WALL_VALUE);
|
||||
}
|
||||
|
||||
Point last_even{0,0};
|
||||
void maze::divide(Matrix& maze, Point start, Point end) {
|
||||
for(matrix::line it{start, end}; it.next();) {
|
||||
maze[it.y][it.x] = 0;
|
||||
maze[it.y+1][it.x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& room : rooms) {
|
||||
if(room.x % 2 == 0 && room.y % 2 == 0) {
|
||||
last_even = {room.x, room.y};
|
||||
void maze::hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Point>& dead_ends, bool init_map) {
|
||||
|
||||
if(init_map) {
|
||||
maze::init(maze);
|
||||
}
|
||||
|
||||
for(auto& room : rooms) {
|
||||
for(matrix::box it{maze, room.x, room.y, room.width}; it.next();) {
|
||||
maze[it.y][it.x] = 0;
|
||||
}
|
||||
|
@ -149,3 +172,34 @@ void maze::hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Poi
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void maze::inner_ring(Matrix& maze, size_t outer_size, size_t inner_size) {
|
||||
|
||||
size_t x = matrix::width(maze) / 2;
|
||||
size_t y = matrix::height(maze) / 2;
|
||||
|
||||
for(matrix::box it{maze, x, y, outer_size};
|
||||
it.next();)
|
||||
{
|
||||
maze[it.y][it.x] = 0;
|
||||
}
|
||||
|
||||
for(matrix::box it{maze, x, y, inner_size};
|
||||
it.next();)
|
||||
{
|
||||
maze[it.y][it.x] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maze::remove_dead_ends(Matrix& maze, std::vector<Point>& dead_ends) {
|
||||
for(auto at : dead_ends) {
|
||||
for(matrix::compass it{maze, at.x, at.y}; it.next();) {
|
||||
if(maze[it.y][it.x] == 0) {
|
||||
int diff_x = at.x - it.x;
|
||||
int diff_y = at.y - it.y;
|
||||
maze[at.y + diff_y][at.x + diff_x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
maze.hpp
13
maze.hpp
|
@ -3,5 +3,16 @@
|
|||
#include "map.hpp"
|
||||
|
||||
namespace maze {
|
||||
void hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Point>& dead_ends);
|
||||
|
||||
void init(Matrix& maze);
|
||||
|
||||
void hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Point>& dead_ends, bool init_map=true);
|
||||
|
||||
void randomize_rooms(std::vector<Room>& rooms_out, std::vector<Point> maybe_here);
|
||||
|
||||
void inner_ring(Matrix& map, size_t outer_size, size_t inner_size);
|
||||
|
||||
void divide(Matrix& maze, Point start, Point end);
|
||||
|
||||
void remove_dead_ends(Matrix& maze, std::vector<Point>& dead_ends);
|
||||
}
|
||||
|
|
|
@ -10,16 +10,94 @@ using std::string;
|
|||
using matrix::Matrix;
|
||||
|
||||
|
||||
TEST_CASE("hunt-and-kill", "[maze-gen]") {
|
||||
TEST_CASE("hunt-and-kill", "[mazes]") {
|
||||
auto map = matrix::make(21, 21);
|
||||
std::vector<Room> rooms;
|
||||
std::vector<Point> dead_ends;
|
||||
|
||||
maze::hunt_and_kill(map, rooms, dead_ends);
|
||||
matrix::dump("MAZE?", map);
|
||||
matrix::dump("BASIC MAZE", map);
|
||||
|
||||
maze::randomize_rooms(rooms, dead_ends);
|
||||
maze::hunt_and_kill(map, rooms, dead_ends);
|
||||
|
||||
for(auto& room : rooms) {
|
||||
fmt::println("room: {},{}; {},{}",
|
||||
room.x, room.y, room.width, room.height);
|
||||
for(matrix::box it{map, room.x, room.y, room.width};
|
||||
it.next();)
|
||||
{
|
||||
map[it.y][it.x] = WALL_PATH_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
matrix::dump("MAZE WITH ROOMS", map);
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill ring", "[mazes]") {
|
||||
auto map = matrix::make(21, 21);
|
||||
std::vector<Room> rooms;
|
||||
std::vector<Point> dead_ends;
|
||||
|
||||
maze::init(map);
|
||||
maze::inner_ring(map, 5, 2);
|
||||
maze::hunt_and_kill(map, rooms, dead_ends, false);
|
||||
|
||||
for(auto at : dead_ends) {
|
||||
map[at.y][at.x]=32;
|
||||
}
|
||||
matrix::dump("RING MAZE", map);
|
||||
|
||||
REQUIRE(rooms.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill fissure", "[mazes]") {
|
||||
auto map = matrix::make(21, 21);
|
||||
std::vector<Room> rooms;
|
||||
std::vector<Point> dead_ends;
|
||||
|
||||
maze::init(map);
|
||||
maze::divide(map, {3,3}, {19,18});
|
||||
maze::hunt_and_kill(map, rooms, dead_ends, false);
|
||||
|
||||
for(auto at : dead_ends) {
|
||||
map[at.y][at.x]=32;
|
||||
}
|
||||
matrix::dump("FISSURE MAZE", map);
|
||||
|
||||
REQUIRE(rooms.size() == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("hunt-and-kill no-dead-ends", "[mazes]") {
|
||||
auto map = matrix::make(21, 21);
|
||||
std::vector<Room> rooms;
|
||||
std::vector<Point> dead_ends;
|
||||
|
||||
maze::init(map);
|
||||
|
||||
maze::hunt_and_kill(map, rooms, dead_ends, false);
|
||||
|
||||
maze::remove_dead_ends(map, dead_ends);
|
||||
|
||||
matrix::dump("NO DEAD ENDS", map);
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill too much", "[mazes]") {
|
||||
auto map = matrix::make(21, 21);
|
||||
std::vector<Room> rooms;
|
||||
std::vector<Point> dead_ends;
|
||||
|
||||
maze::init(map);
|
||||
maze::inner_ring(map, 4, 2);
|
||||
maze::divide(map, {3,3}, {19,18});
|
||||
auto copy = map;
|
||||
|
||||
maze::hunt_and_kill(copy, rooms, dead_ends, false);
|
||||
|
||||
|
||||
map = copy;
|
||||
maze::randomize_rooms(rooms, dead_ends);
|
||||
maze::hunt_and_kill(map, rooms, dead_ends, false);
|
||||
|
||||
matrix::dump("NO DEAD ENDS", map);
|
||||
}
|
||||
|
|
|
@ -14,13 +14,8 @@ void WorldBuilder::generate_map() {
|
|||
// run it once to find dead ends
|
||||
maze::hunt_and_kill($map.$walls, $map.$rooms, $map.$dead_ends);
|
||||
|
||||
// use those dead ends to randomly place rooms
|
||||
for(auto at : $map.$dead_ends) {
|
||||
if(Random::uniform(0,1)) {
|
||||
Room cur{at.x, at.y, 2, 2};
|
||||
$map.add_room(cur);
|
||||
}
|
||||
}
|
||||
// randomize rooms based on dead ends
|
||||
maze::randomize_rooms($map.$rooms, $map.$dead_ends);
|
||||
|
||||
// run it again to create the final map with rooms
|
||||
// NOTE: hund_and_kill is responsible for clearing the map correctly
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue