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
|
meson compile -j 10 -C builddir
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
./builddir/runtests
|
./builddir/runtests "[mazes]"
|
||||||
|
|
||||||
run: build test
|
run: build test
|
||||||
ifeq '$(OS)' 'Windows_NT'
|
ifeq '$(OS)' 'Windows_NT'
|
||||||
|
@ -49,7 +49,7 @@ clean:
|
||||||
meson compile --clean -C builddir
|
meson compile --clean -C builddir
|
||||||
|
|
||||||
debug_test: build
|
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:
|
win_installer:
|
||||||
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'
|
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'
|
||||||
|
|
|
@ -100,6 +100,11 @@
|
||||||
"frame_width": 256,
|
"frame_width": 256,
|
||||||
"frame_height": 256
|
"frame_height": 256
|
||||||
},
|
},
|
||||||
|
"lava_floor":
|
||||||
|
{"path": "assets/lava_floor-256.png",
|
||||||
|
"frame_width": 256,
|
||||||
|
"frame_height": 256
|
||||||
|
},
|
||||||
"ceiling":
|
"ceiling":
|
||||||
{"path": "assets/ceiling_test-256.png",
|
{"path": "assets/ceiling_test-256.png",
|
||||||
"frame_width": 256,
|
"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) {
|
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);
|
$rooms.push_back(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
68
maze.cpp
68
maze.cpp
|
@ -93,16 +93,39 @@ inline std::pair<Point, Point> find_coord(Matrix& maze) {
|
||||||
dbc::sentinel("failed to find coord?");
|
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) {
|
||||||
matrix::assign(maze, WALL_VALUE);
|
dbc::check(maybe_here.size() >= 2, "must have at least two possible points to place rooms");
|
||||||
|
|
||||||
Point last_even{0,0};
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(auto& room : rooms) {
|
||||||
if(room.x % 2 == 0 && room.y % 2 == 0) {
|
|
||||||
last_even = {room.x, room.y};
|
|
||||||
}
|
|
||||||
|
|
||||||
for(matrix::box it{maze, room.x, room.y, room.width}; it.next();) {
|
for(matrix::box it{maze, room.x, room.y, room.width}; it.next();) {
|
||||||
maze[it.y][it.x] = 0;
|
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"
|
#include "map.hpp"
|
||||||
|
|
||||||
namespace maze {
|
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;
|
using matrix::Matrix;
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("hunt-and-kill", "[maze-gen]") {
|
TEST_CASE("hunt-and-kill", "[mazes]") {
|
||||||
auto map = matrix::make(21, 21);
|
auto map = matrix::make(21, 21);
|
||||||
std::vector<Room> rooms;
|
std::vector<Room> rooms;
|
||||||
std::vector<Point> dead_ends;
|
std::vector<Point> dead_ends;
|
||||||
|
|
||||||
maze::hunt_and_kill(map, rooms, 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) {
|
for(auto& room : rooms) {
|
||||||
fmt::println("room: {},{}; {},{}",
|
for(matrix::box it{map, room.x, room.y, room.width};
|
||||||
room.x, room.y, room.width, room.height);
|
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
|
// run it once to find dead ends
|
||||||
maze::hunt_and_kill($map.$walls, $map.$rooms, $map.$dead_ends);
|
maze::hunt_and_kill($map.$walls, $map.$rooms, $map.$dead_ends);
|
||||||
|
|
||||||
// use those dead ends to randomly place rooms
|
// randomize rooms based on dead ends
|
||||||
for(auto at : $map.$dead_ends) {
|
maze::randomize_rooms($map.$rooms, $map.$dead_ends);
|
||||||
if(Random::uniform(0,1)) {
|
|
||||||
Room cur{at.x, at.y, 2, 2};
|
|
||||||
$map.add_room(cur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// run it again to create the final map with rooms
|
// run it again to create the final map with rooms
|
||||||
// NOTE: hund_and_kill is responsible for clearing the map correctly
|
// NOTE: hund_and_kill is responsible for clearing the map correctly
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue