diff --git a/assets/config.json b/assets/config.json index bc0ff49..ab36b4d 100644 --- a/assets/config.json +++ b/assets/config.json @@ -323,7 +323,6 @@ }, "worldgen": { "enemy_probability": 50, - "empty_room_probability": 1, "device_probability": 10 }, "graphics": { diff --git a/assets/devices.json b/assets/devices.json index d0d2335..9108d00 100644 --- a/assets/devices.json +++ b/assets/devices.json @@ -40,7 +40,7 @@ "description": "Watch where you're going.", "inventory_count": 0, "components": [ - {"_type": "Tile", "display": 6855, + {"_type": "Tile", "display": 95, "foreground": [24, 205, 189], "background": [24, 205, 189] }, diff --git a/assets/items.json b/assets/items.json index a8f6df3..e7f2a15 100644 --- a/assets/items.json +++ b/assets/items.json @@ -34,7 +34,7 @@ "name": "Small Barrel", "description": "A small rotten barrel that may hold things.", "components": [ - {"_type": "Tile", "display": 43754, + {"_type": "Tile", "display": 85, "foreground": [150, 100, 189], "background": [150, 100, 189] }, diff --git a/map.hpp b/map.hpp index 1dccbe2..04b1bee 100644 --- a/map.hpp +++ b/map.hpp @@ -19,8 +19,6 @@ struct Room { size_t y = 0; size_t width = 0; size_t height = 0; - Point entry{(size_t)-1, (size_t)-1}; - Point exit{(size_t)-1, (size_t)-1}; }; class Map { @@ -31,6 +29,7 @@ public: Matrix $walls; Pathing $paths; std::vector $rooms; + std::vector $dead_ends; Map(size_t width, size_t height); diff --git a/maze.cpp b/maze.cpp index 630c45c..4b785c7 100644 --- a/maze.cpp +++ b/maze.cpp @@ -28,7 +28,6 @@ inline bool complete(Matrix& maze) { } } - // dbc::sentinel("LOL it's complete eh?"); return true; } @@ -136,6 +135,7 @@ void maze::hunt_and_kill(Matrix& maze, std::vector& rooms, std::vector= room_ul.x && at.y >= room_ul.y && at.x <= room_lr.x && at.y <= room_lr.y) { diff --git a/worldbuilder.cpp b/worldbuilder.cpp index 6a3abbe..367f13d 100644 --- a/worldbuilder.cpp +++ b/worldbuilder.cpp @@ -10,70 +10,28 @@ using namespace fmt; using namespace components; -inline int make_split(Room &cur, bool horiz) { - size_t dimension = horiz ? cur.height : cur.width; - int min = dimension / WORLDBUILD_DIVISION; - int max = dimension - min; - - return Random::uniform(min, max); -} - -void rand_side(Room &room, Point &door) { - dbc::check(int(room.width) > 0 && int(room.height) > 0, "Weird room with 0 for height or width."); - int rand_x = Random::uniform(0, room.width - 1); - int rand_y = Random::uniform(0, room.height - 1); - - switch(Random::uniform(0,3)) { - case 0: // north - door.x = room.x + rand_x; - door.y = room.y-1; - break; - case 1: // south - door.x = room.x + rand_x; - door.y = room.y + room.height; - break; - case 2: // east - door.x = room.x + room.width; - door.y = room.y + rand_y; - break; - case 3: // west - door.x = room.x - 1; - door.y = room.y + rand_y; - break; - default: - dbc::sentinel("impossible side"); - } -} - -void WorldBuilder::add_door(Room &room) { - rand_side(room, room.entry); - rand_side(room, room.exit); -} - void WorldBuilder::generate_map() { - std::vector dead_ends; - maze::hunt_and_kill($map.$walls, $map.$rooms, dead_ends); + // run it once to find dead ends + maze::hunt_and_kill($map.$walls, $map.$rooms, $map.$dead_ends); - for(auto at : 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}; - add_door(cur); $map.add_room(cur); } } - maze::hunt_and_kill($map.$walls, $map.$rooms, dead_ends); + // run it again to create the final map with rooms + // NOTE: hund_and_kill is responsible for clearing the map correctly + maze::hunt_and_kill($map.$walls, $map.$rooms, $map.$dead_ends); $map.expand(); $map.load_tiles(); } - -DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, int in_room) { +DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, Point pos_out) { auto item = world.entity(); - Point pos_out; - bool placed = $map.place_entity(in_room, pos_out); - dbc::check(placed, "failed to randomly place item in room"); world.set(item, {pos_out.x+1, pos_out.y+1}); if(entity_data["inventory_count"] > 0) { @@ -86,6 +44,14 @@ DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, j return item; } +DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, int in_room) { + Point pos_out; + bool placed = $map.place_entity(in_room, pos_out); + dbc::check(placed, "failed to randomly place item in room"); + return configure_entity_in_map(world, entity_data, pos_out); +} + + inline json &select_entity_type(GameConfig &config, json &gen_config) { int enemy_test = Random::uniform(0,100); int device_test = Random::uniform(0, 100); @@ -99,32 +65,37 @@ inline json &select_entity_type(GameConfig &config, json &gen_config) { } } -void WorldBuilder::randomize_entities(DinkyECS::World &world, GameConfig &config) { - auto &gen_config = config.game["worldgen"]; - - for(size_t room_num = $map.room_count() - 1; room_num > 0; room_num--) { - int empty_room = Random::uniform(0, 100); - if(empty_room < gen_config["empty_room_probability"]) continue; - - json& entity_db = select_entity_type(config, gen_config); +inline json& random_entity_data(GameConfig& config, json& gen_config) { + json& entity_db = select_entity_type(config, gen_config); - std::vector keys; - for(auto& el : entity_db.items()) { - auto& data = el.value(); + std::vector keys; + for(auto& el : entity_db.items()) { + auto& data = el.value(); - if(data["placement"] == nullptr) { - keys.push_back(el.key()); - } + if(data["placement"] == nullptr) { + keys.push_back(el.key()); } + } + + int rand_entity = Random::uniform(0, keys.size() - 1); + std::string key = keys[rand_entity]; + // BUG: this may crash if PLAYER_TILE isn't first + return entity_db[key]; +} - int rand_entity = Random::uniform(0, keys.size() - 1); - std::string key = keys[rand_entity]; - // BUG: this may crash if PLAYER_TILE isn't first - auto entity_data = entity_db[key]; +void WorldBuilder::randomize_entities(DinkyECS::World &world, GameConfig &config) { + auto& gen_config = config.game["worldgen"]; + for(size_t room_num = $map.room_count() - 1; room_num > 0; room_num--) { // pass that to the config as it'll be a generic json + auto& entity_data = random_entity_data(config, gen_config); configure_entity_in_map(world, entity_data, room_num); } + + for(auto& at : $map.$dead_ends) { + auto& entity_data = random_entity_data(config, gen_config); + configure_entity_in_map(world, entity_data, at); + } } void WorldBuilder::place_stairs(DinkyECS::World& world, GameConfig& config) { diff --git a/worldbuilder.hpp b/worldbuilder.hpp index d8d0356..d92e126 100644 --- a/worldbuilder.hpp +++ b/worldbuilder.hpp @@ -14,10 +14,12 @@ class WorldBuilder { $components(components) { } - void add_door(Room &room); void generate_map(); + DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, nlohmann::json &entity_data, Point pos); + DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, nlohmann::json &entity_data, int in_room); + void place_entities(DinkyECS::World &world); void generate(DinkyECS::World &world); void randomize_entities(DinkyECS::World &world, components::GameConfig &config);