Random map gen is mostly working, now to clean it up.

main
Zed A. Shaw 10 months ago
parent a82944f55a
commit 3a43324fa2
  1. 16
      main.cpp
  2. 140
      map.cpp
  3. 22
      map.hpp

@ -28,35 +28,31 @@ int main() {
auto c = Canvas(60 * 2, 27 * 4);
Map game_map(60, 27);
Map game_map(50, 27);
game_map.generate();
Matrix &input_map = game_map.input_map();
Matrix &walls = game_map.walls();
// place character
// input_map[10][10] = 0;
auto map = Renderer([&] {
Matrix &result = game_map.paths();
Matrix &walls = game_map.walls();
for(size_t x = 0; x < result[0].size(); ++x) {
for(size_t y = 0; y < result.size(); ++y) {
auto path = result[y][x];
if(path == 1000) {
if(path == 1000 || walls[y][x] == 1) {
// it's a wall or unreachable, use the wall_map
const string tile = walls[y][x] == 1 ? "#" : ".";
c.DrawText(x*2, y*4, tile, Color::Yellow);
c.DrawText(x*2, y*4, tile, Color::GrayDark);
} else {
// it's a path number, show it
const string tile = format("{}", path);
Color color = path == 0 ? Color::Red : Color::GrayDark;
auto color = Color::Palette16(path % 7 + 1);
c.DrawText(x*2, y*4, tile, color);
}
}
}
// draw the character
c.DrawText(10*2, 10*4, "@", Color::Blue);
//c.DrawText(10*2, 10*4, "@", Color::Blue);
return canvas(c);
});

@ -5,7 +5,6 @@
#include <random>
#include <utility>
std::random_device g_rng;
std::mt19937 g_generator(g_rng());
@ -41,8 +40,13 @@ inline void add_neighbors(PairList &neighbors, Matrix &closed, size_t j, size_t
}
}
/**
* This will create an _inverted_ map that you
* can run make_rooms and generate on. It will
* NOT be valid until you actually run generate.
*/
Map::Map(size_t width, size_t height) : m_limit(1000) {
m_walls = Matrix(height, MatrixRow(width, 0));
m_walls = Matrix(height, MatrixRow(width, INV_WALL));
m_input_map = Matrix(height, MatrixRow(width, 1));
}
@ -103,18 +107,15 @@ void Map::make_room(size_t origin_x, size_t origin_y, size_t w, size_t h) {
dbc::check(y < m_walls.size(), "y is out of bounds");
for(size_t x = origin_x; x < origin_x + w; ++x) {
dbc::check(x < m_walls[y].size(), "x is out of bounds");
m_walls[y][x] = 1;
m_walls[y][x] = INV_SPACE;
}
}
}
inline int make_split(Room &cur, bool horiz) {
println("MAKE SPLIT horiz={}, y={}, w={}, h={}", horiz,
cur.y, cur.width, cur.height);
size_t dimension = horiz ? cur.height : cur.width;
int min = dimension / 4;
int max = dimension - min;
println("dimension={}, min={}, max={}", dimension, min, max);
std::uniform_int_distribution<int> rand_dim(min, max);
return rand_dim(g_generator);
}
@ -158,13 +159,96 @@ void Map::partition_map(Room &cur, int depth) {
void Map::place_rooms(Room &cur) {
for(auto &cur : m_rooms) {
make_room(cur.x+1, cur.y+1, cur.width-2, cur.height-2);
cur.door_x = cur.x+1;
cur.door_y = cur.y;
m_input_map[cur.door_y][cur.door_x] = 0;
cur.x += 2;
cur.y += 2;
cur.width -= 4;
cur.height -= 4;
add_door(cur);
set_door(cur, INV_SPACE);
make_room(cur.x, cur.y, cur.width, cur.height);
}
}
bool Map::neighbors(Point &out, bool greater) {
std::array<Point, 4> dirs{{
{out.x,out.y-1},
{out.x+1,out.y},
{out.x,out.y+1},
{out.x-1,out.y}
}};
int zero_i = -1;
int cur = m_paths[out.y][out.x];
dbc::check(cur != 1000, "WRONG! start point is in a wall");
for(int i = 0; i < 4; ++i) {
Point dir = dirs[i];
int diff = inmap(dir.x, dir.y) ? cur - m_paths[dir.y][dir.x] : -1000;
if(diff == 1) {
out = {.x=dir.x, .y=dir.y};
return true;
} else if(diff == 0) {
zero_i = i;
}
}
if(zero_i != -1) {
out = {.x=dirs[zero_i].x, .y=dirs[zero_i].y};
return true;
} else {
return false;
}
}
bool Map::inmap(size_t x, size_t y) {
return x < width() && y < height();
}
void Map::set_door(Room &room, int value) {
m_walls[room.entry.y][room.entry.x] = value;
m_walls[room.exit.y][room.exit.x] = value;
}
void Map::add_door(Room &room) {
room.entry.x = room.x;
room.entry.y = room.y-1;
room.exit.x = room.x + room.width - 1;
room.exit.y = room.y + room.height;
}
bool Map::walk(Room &src, Room &target) {
// this sets the target for the path
dbc::check(m_input_map[target.entry.y][target.entry.x] == 0, "target point not set to 0");
m_walls[src.exit.y][src.exit.x] = INV_WALL;
m_walls[target.entry.y][target.entry.x] = INV_WALL;
// for the walk this needs to be walls since it's inverted?
dbc::check(m_walls[src.exit.y][src.exit.x] == INV_WALL,
"src room has a wall at exit door");
dbc::check(m_walls[target.entry.y][target.entry.x] == INV_WALL,
"target room has a wall at entry door");
make_paths();
bool found = false;
int count = 0;
Point out{src.exit.x, src.exit.y};
do {
m_walls[out.y][out.x] = INV_SPACE;
found = neighbors(out, true);
if(m_paths[out.y][out.x] == 0) {
m_walls[out.y][out.x] = INV_SPACE;
return true;
}
} while(found && out.x > 0 && out.y > 0);
return false;
}
void Map::generate() {
Room root{
.x = 0,
@ -175,19 +259,29 @@ void Map::generate() {
partition_map(root, 10);
place_rooms(root);
make_paths();
Room &room0 = m_rooms[0];
Room &room1 = m_rooms[1];
int cur = m_paths[room0.door_y][room0.door_x];
int next = m_paths[room0.door_y][room0.door_x+1];
int i = 1;
while(next >= cur) {
cur = next;
next = m_paths[room0.door_y][room0.door_x+i];
++i;
println("door_y: {}, door_x: {}, CUR: {}, NEXT: {}", room0.door_y, room0.door_x, cur, next);
for(size_t i = 0; i < m_rooms.size() - 1; i++) {
Room &src = m_rooms[i];
Room &target = m_rooms[i+1];
m_input_map[target.entry.y][target.entry.x] = 0;
bool found = walk(src, target);
if(!found) {
println("ROOM NOT FOUND!");
}
m_input_map[target.entry.y][target.entry.x] = 1;
}
Room &src = m_rooms[m_rooms.size()-1];
Room &target = m_rooms[0];
m_input_map[target.entry.y][target.entry.x] = 0;
walk(src, target);
dump_map("WALLS", m_walls);
for(size_t y = 0; y < height(); ++y) {
for(size_t x = 0; x < width(); ++x) {
m_walls[y][x] = !m_walls[y][x];
}
}
}

@ -4,6 +4,17 @@
#include <string>
#include <random>
#define INV_WALL 0
#define INV_SPACE 1
#define WALL_VALUE 1
#define SPACE_VALUE 0
struct Point {
size_t x = 0;
size_t y = 0;
};
struct Pair {
size_t j = 0;
size_t i = 0;
@ -16,10 +27,8 @@ struct Room {
size_t y = 0;
size_t width = 0;
size_t height = 0;
size_t door_x = 0;
size_t door_y = 0;
std::vector<Room> next;
Point entry;
Point exit;
};
typedef std::vector<Pair> PairList;
@ -58,9 +67,14 @@ public:
void make_room(size_t origin_y, size_t origin_x, size_t width, size_t height);
void add_door(Room &room);
bool inmap(size_t x, size_t y);
bool neighbors(Point &out, bool up);
void generate();
void place_rooms(Room &root);
void make_paths();
void partition_map(Room &cur, int depth);
bool walk(Room &src, Room &target);
void set_door(Room &room, int value);
void dump();
};

Loading…
Cancel
Save