#include "worldbuilder.hpp" #include "rand.hpp" #include #include #include "components.hpp" #include "inventory.hpp" #include "rituals.hpp" #include "maze.hpp" using namespace fmt; using namespace components; void WorldBuilder::generate_map() { maze::init($map.$walls); maze::hunt_and_kill($map.$walls, $map.$rooms, $map.$dead_ends); maze::randomize_rooms($map.$rooms, $map.$dead_ends); 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, Point pos_out) { dbc::log(">>>>>>>>>>> ENTER"); auto item = world.entity(); world.set(item, {pos_out.x+1, pos_out.y+1}); if(entity_data["inventory_count"] > 0) { world.set(item, {entity_data["inventory_count"], entity_data}); } if(entity_data.contains("components")) { components::configure_entity($components, world, item, entity_data["components"]); } dbc::log("<<<<<<<<<<<<< EXIT"); return item; } DinkyECS::Entity WorldBuilder::configure_entity_in_room(DinkyECS::World &world, json &entity_data, int in_room) { Point pos_out; dbc::log("is it configure_entity_in_map's fault?"); bool placed = $map.place_entity(in_room, pos_out); dbc::check(placed, "failed to randomly place item in room"); auto entity = configure_entity_in_map(world, entity_data, pos_out); dbc::log("<<<<<<<<<<<<<<<<<<<<<<<<<<< leaving configure_entity_in_room"); return entity; } inline json &select_entity_type(GameConfig &config, json &gen_config) { int enemy_test = Random::uniform(0,100); int device_test = Random::uniform(0, 100); if(enemy_test < gen_config["enemy_probability"]) { return config.enemies.json(); } else if(device_test < gen_config["device_probability"]) { return config.devices.json(); } else { return config.items.json(); } } 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(); 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]; } void WorldBuilder::randomize_entities(DinkyECS::World &world, GameConfig &config) { auto& gen_config = config.game["worldgen"]; for(int 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_room(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) { auto& device_config = config.devices.json(); auto entity_data = device_config["STAIRS_DOWN"]; int last_room = $map.room_count() - 1; configure_entity_in_room(world, entity_data, last_room); } void WorldBuilder::configure_starting_items(DinkyECS::World &world) { auto& blanket = world.get_the(); Config config("assets/rituals.json"); for(auto& el : config["starting_junk"]) { ritual::JunkItem name = el; blanket.add(name); }; } void WorldBuilder::place_entities(DinkyECS::World &world) { auto &config = world.get_the(); // configure a player as a fact of the world if(world.has_the()) { auto& player = world.get_the(); Point pos_out; dbc::log("or is it in place_entities placing the player?"); bool placed = $map.place_entity(0, pos_out); dbc::check(placed, "failed to randomly place item in room"); world.set(player.entity, {pos_out.x+1, pos_out.y+1}); } else { auto player_data = config.enemies["PLAYER_TILE"]; auto player_ent = configure_entity_in_room(world, player_data, 0); // configure player in the world Player player{player_ent}; world.set_the(player); world.set_the({}); world.set_the({}); configure_starting_items(world); world.set(player.entity, {5}); world.make_constant(player.entity); } randomize_entities(world, config); place_stairs(world, config); } void WorldBuilder::generate(DinkyECS::World &world) { generate_map(); place_entities(world); }