From 83b05b0f89c80030602548b287de0fd0a0aada7f Mon Sep 17 00:00:00 2001 From: Peisong Xiao Date: Fri, 12 Jul 2024 12:07:38 -0400 Subject: [PATCH] Unfinished: rand map gen --- src/main.cc | 10 ++--- src/map.cc | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/map.h | 25 ++++++++++- 3 files changed, 152 insertions(+), 6 deletions(-) diff --git a/src/main.cc b/src/main.cc index 30069a2..ab2e35a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -19,12 +19,12 @@ int main(int argc, char **argv) { return RETURN_PANICKED; } - CC3K game_proc(enabled_features, *in, *out, *log, *rng); + // CC3K game_proc(enabled_features, *in, *out, *log, *rng); - while (game_proc.run() != game_status::terminated) { - out->render(); - out->clear(); - } + // while (game_proc.run() != game_status::terminated) { + // out->render(); + // out->clear(); + // } return RETURN_FINE; } diff --git a/src/map.cc b/src/map.cc index 5a9a787..12af10c 100644 --- a/src/map.cc +++ b/src/map.cc @@ -1,8 +1,68 @@ #include "map.h" +#include +#include + game_map::game_map(RNG &rng, const feature enabled_features): enabled_features{enabled_features} { + map.reserve(MAP_HEIGHT * MAP_WIDTH); + for (int i = MAP_HEIGHT * MAP_WIDTH; i > 0; --i) + map.push_back(-1); + + // Note: during generation, walls DO NOT count as being in the rooms + std::vector> room_dims = gen_room_dims(rng); + + // width height top left + std::vector> room_data = distr_rooms(rng, + room_dims); + +} + +std::vector> game_map::distr_rooms(RNG &rng, +std::vector> &room_dims) { + std::vector> result{room_dims.size()}; + + int max_layer = room_dims[room_dims.size() - 1].second; + std::vector layer_heights{max_layer + 1}; + + // distributing rooms horizontally + for (int layer = 0; layer <= max_layer; ++layer) { + int l = INF; + int r = 0; + int layer_height = 0; + + // get the interval for the current layer + // and the max height of the layer + for (std::size_t i = 0; i < room_dims.size(); ++i) + if (room_dims[i].second == layer) { + l = std::min(l, (int)i); + r = std::max(r, (int)i); + layer_height = std::max(layer_height, + room_dims[i].first.y); + } + + layer_heights.push_back(layer_height); + + // distribute the current layer + if (l == r) { + result.push_back({room_dims[l].first, + {rng.rand_under(ACTUAL_MAP_WIDTH - room_dims[l].first.x + 1), 0}}); + continue; + } + + int left = room_dims[l].first.x; + int right = ACTUAL_MAP_WIDTH; + + // every time, distribute the last one first + for (int i = l + 1; i < r; ++i) + left += MIN_ROOM_SPACING + room_dims[i].first.x; + + for (int i = r; i > l; --i) { + } + } + + return result; } game_map::game_map(const std::string &map_data, @@ -39,6 +99,12 @@ const position_list game_map::get_available_positions() const { return empty_spots; } +bool game_map::is_available(const position &pos) const { + int idx = remap_position(pos); + return map[idx] <= 9 || map[idx] == '\\' || map[idx] == '>' || + map[idx] == '<' || map[idx] == '+' || map[idx] == '#'; +} + void game_map::print(display &out) const { for (std::size_t i = 0; i < map.size(); ++i) out.print_char(remap_index(i), map[i] <= 9 ? '.' : map[i], @@ -80,3 +146,60 @@ const std::vectorgame_map::get_room_list() const { return result; } + +std::vector> game_map::gen_room_dims(RNG &rng) { + position_list room_dim_list{MAX_ROOM_CNT}; + std::vector> result{MAX_ROOM_CNT}; + + for (int i = 0; i < MAX_ROOM_CNT; ++i) + room_dim_list.push_back(random_size(MIN_ROOM_WIDTH, MIN_ROOM_HEIGHT, + MAX_ROOM_WIDTH, MAX_ROOM_HEIGHT, + rng)); + + int curr_top = 0; + int curr_left = 0; + // index in result + int curr_layer_idx = 0; + int curr_layer_cnt = 0; + + for (int i = 0; i < MAX_ROOM_CNT && + curr_top <= ACTUAL_MAP_HEIGHT && + curr_left <= ACTUAL_MAP_WIDTH; ++i) { + // DO NOT update curr_top until curr_left is exhausted + if (curr_top + MIN_ROOM_SPACING + + room_dim_list[i].y + HEIGHT_RESERVED <= ACTUAL_MAP_HEIGHT && + curr_left + MIN_ROOM_SPACING + + room_dim_list[i].x + WIDTH_RESERVED <= ACTUAL_MAP_WIDTH) { + result.push_back({room_dim_list[i], curr_layer_cnt}); + continue; + } + + int tmp = curr_top; + + for (std::size_t j = curr_layer_idx; j < result.size(); ++j) + tmp = std::max(curr_top + result[j].first.y + MIN_ROOM_SPACING, + tmp); + + curr_top = tmp; + curr_layer_idx = result.size(); + curr_left = 0; + ++curr_layer_cnt; + + if (curr_top + MIN_ROOM_SPACING + + room_dim_list[i].y + HEIGHT_RESERVED <= ACTUAL_MAP_HEIGHT && + curr_left + MIN_ROOM_SPACING + + room_dim_list[i].x + WIDTH_RESERVED <= ACTUAL_MAP_WIDTH) + result.push_back({room_dim_list[i], curr_layer_cnt}); + } + + result.shrink_to_fit(); + + return result; +} + +position random_size(int min_width, int min_height, + int max_width, int max_height, + RNG &rng) { + return {rng.rand_between(min_width, max_width + 1), + rng.rand_between(min_height, max_height + 1)}; +} diff --git a/src/map.h b/src/map.h index 2585cbf..101de03 100644 --- a/src/map.h +++ b/src/map.h @@ -2,14 +2,27 @@ #define __MAP_H__ #include #include +#include #include "constants.h" #include "display.h" #include "position.h" -#include "characters.h" #include "rng.h" class game_map final { private: + static const int MAX_ROOM_CNT = 20; + static const int MIN_ROOM_WIDTH = 3; + static const int MIN_ROOM_HEIGHT = 3; + static const int MAX_ROOM_WIDTH = 20; + static const int MAX_ROOM_HEIGHT = 13; + // setup safezones + static const int ACTUAL_MAP_WIDTH = MAP_WIDTH - 4; + static const int ACTUAL_MAP_HEIGHT = MAP_HEIGHT - 4; + static const int MAP_PADDING = 1; + static const int MIN_ROOM_SPACING = 4; + static const int WIDTH_RESERVED = 8; + static const int HEIGHT_RESERVED = 4; + const feature enabled_features; std::vector map; // IMPORTANT: keep empty_spots ordered @@ -25,6 +38,7 @@ public: const feature enabled_features); const position_list get_available_positions() const; + bool is_available(const position &pos) const; const std::vector get_room_list() const; // IMPORTANT: always print a map before anything else @@ -43,6 +57,15 @@ private: int remap_position(const position &pos) const { return pos.y * MAP_WIDTH + pos.x; } + + position random_size(int min_width, int min_height, + int max_width, int max_height, + RNG &rng); + + std::vector> gen_room_dims(RNG &rng); + std::vector> distr_rooms(RNG &rng, + std::vector> + &room_dims); }; const std::string default_map =