Maze works well now and there's something placed in all rooms and dead ends. Will need to randomize it more so not every dead end is an enemy.
This commit is contained in:
parent
a0b785cb2a
commit
ac252bf09d
7 changed files with 48 additions and 77 deletions
111
worldbuilder.cpp
111
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<int>(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<int>(0, room.width - 1);
|
||||
int rand_y = Random::uniform<int>(0, room.height - 1);
|
||||
|
||||
switch(Random::uniform<int>(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<Point> 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<Position>(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<int>(0,100);
|
||||
int device_test = Random::uniform<int>(0, 100);
|
||||
|
@ -99,32 +65,37 @@ inline json &select_entity_type(GameConfig &config, json &gen_config) {
|
|||
}
|
||||
}
|
||||
|
||||
inline json& random_entity_data(GameConfig& config, json& gen_config) {
|
||||
json& entity_db = select_entity_type(config, gen_config);
|
||||
|
||||
std::vector<std::string> 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<int>(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"];
|
||||
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<int>(0, 100);
|
||||
if(empty_room < gen_config["empty_room_probability"]) continue;
|
||||
|
||||
json& entity_db = select_entity_type(config, gen_config);
|
||||
|
||||
std::vector<std::string> 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<int>(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];
|
||||
|
||||
// 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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue