Playing with maze gen again.

master
Zed A. Shaw 2 weeks ago
parent c97648ab3a
commit 33cd490ed3
  1. 4
      Makefile
  2. 5
      assets/config.json
  3. BIN
      assets/lava_floor-256.png
  4. 15
      map.cpp
  5. 66
      maze.cpp
  6. 13
      maze.hpp
  7. 86
      tests/mazes.cpp
  8. 9
      worldbuilder.cpp

@ -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,

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

@ -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);
}

@ -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);
}
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;
}
}
Point last_even{0,0};
void maze::hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Point>& dead_ends, bool init_map) {
for(auto& room : rooms) {
if(room.x % 2 == 0 && room.y % 2 == 0) {
last_even = {room.x, room.y};
}
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;
}
}
}
}

@ -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…
Cancel
Save