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
|
@ -323,7 +323,6 @@
|
||||||
},
|
},
|
||||||
"worldgen": {
|
"worldgen": {
|
||||||
"enemy_probability": 50,
|
"enemy_probability": 50,
|
||||||
"empty_room_probability": 1,
|
|
||||||
"device_probability": 10
|
"device_probability": 10
|
||||||
},
|
},
|
||||||
"graphics": {
|
"graphics": {
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
"description": "Watch where you're going.",
|
"description": "Watch where you're going.",
|
||||||
"inventory_count": 0,
|
"inventory_count": 0,
|
||||||
"components": [
|
"components": [
|
||||||
{"_type": "Tile", "display": 6855,
|
{"_type": "Tile", "display": 95,
|
||||||
"foreground": [24, 205, 189],
|
"foreground": [24, 205, 189],
|
||||||
"background": [24, 205, 189]
|
"background": [24, 205, 189]
|
||||||
},
|
},
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
"name": "Small Barrel",
|
"name": "Small Barrel",
|
||||||
"description": "A small rotten barrel that may hold things.",
|
"description": "A small rotten barrel that may hold things.",
|
||||||
"components": [
|
"components": [
|
||||||
{"_type": "Tile", "display": 43754,
|
{"_type": "Tile", "display": 85,
|
||||||
"foreground": [150, 100, 189],
|
"foreground": [150, 100, 189],
|
||||||
"background": [150, 100, 189]
|
"background": [150, 100, 189]
|
||||||
},
|
},
|
||||||
|
|
3
map.hpp
3
map.hpp
|
@ -19,8 +19,6 @@ struct Room {
|
||||||
size_t y = 0;
|
size_t y = 0;
|
||||||
size_t width = 0;
|
size_t width = 0;
|
||||||
size_t height = 0;
|
size_t height = 0;
|
||||||
Point entry{(size_t)-1, (size_t)-1};
|
|
||||||
Point exit{(size_t)-1, (size_t)-1};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Map {
|
class Map {
|
||||||
|
@ -31,6 +29,7 @@ public:
|
||||||
Matrix $walls;
|
Matrix $walls;
|
||||||
Pathing $paths;
|
Pathing $paths;
|
||||||
std::vector<Room> $rooms;
|
std::vector<Room> $rooms;
|
||||||
|
std::vector<Point> $dead_ends;
|
||||||
|
|
||||||
Map(size_t width, size_t height);
|
Map(size_t width, size_t height);
|
||||||
|
|
||||||
|
|
2
maze.cpp
2
maze.cpp
|
@ -28,7 +28,6 @@ inline bool complete(Matrix& maze) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dbc::sentinel("LOL it's complete eh?");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +135,7 @@ void maze::hunt_and_kill(Matrix& maze, std::vector<Room>& rooms, std::vector<Poi
|
||||||
for(auto& room : rooms) {
|
for(auto& room : rooms) {
|
||||||
Point room_ul{room.x - room.width - 1, room.y - room.height - 1};
|
Point room_ul{room.x - room.width - 1, room.y - room.height - 1};
|
||||||
Point room_lr{room.x + room.width - 1, room.y + room.height - 1};
|
Point room_lr{room.x + room.width - 1, room.y + room.height - 1};
|
||||||
|
|
||||||
if(at.x >= room_ul.x && at.y >= room_ul.y &&
|
if(at.x >= room_ul.x && at.y >= room_ul.y &&
|
||||||
at.x <= room_lr.x && at.y <= room_lr.y)
|
at.x <= room_lr.x && at.y <= room_lr.y)
|
||||||
{
|
{
|
||||||
|
|
111
worldbuilder.cpp
111
worldbuilder.cpp
|
@ -10,70 +10,28 @@
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
using namespace components;
|
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() {
|
void WorldBuilder::generate_map() {
|
||||||
std::vector<Point> dead_ends;
|
// run it once to find dead ends
|
||||||
maze::hunt_and_kill($map.$walls, $map.$rooms, 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)) {
|
if(Random::uniform(0,1)) {
|
||||||
Room cur{at.x, at.y, 2, 2};
|
Room cur{at.x, at.y, 2, 2};
|
||||||
add_door(cur);
|
|
||||||
$map.add_room(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.expand();
|
||||||
$map.load_tiles();
|
$map.load_tiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, Point pos_out) {
|
||||||
DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, json &entity_data, int in_room) {
|
|
||||||
auto item = world.entity();
|
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});
|
world.set<Position>(item, {pos_out.x+1, pos_out.y+1});
|
||||||
|
|
||||||
if(entity_data["inventory_count"] > 0) {
|
if(entity_data["inventory_count"] > 0) {
|
||||||
|
@ -86,6 +44,14 @@ DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, j
|
||||||
return item;
|
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) {
|
inline json &select_entity_type(GameConfig &config, json &gen_config) {
|
||||||
int enemy_test = Random::uniform<int>(0,100);
|
int enemy_test = Random::uniform<int>(0,100);
|
||||||
int device_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) {
|
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--) {
|
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
|
// 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);
|
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) {
|
void WorldBuilder::place_stairs(DinkyECS::World& world, GameConfig& config) {
|
||||||
|
|
|
@ -14,10 +14,12 @@ class WorldBuilder {
|
||||||
$components(components)
|
$components(components)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void add_door(Room &room);
|
|
||||||
void generate_map();
|
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);
|
DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, nlohmann::json &entity_data, int in_room);
|
||||||
|
|
||||||
void place_entities(DinkyECS::World &world);
|
void place_entities(DinkyECS::World &world);
|
||||||
void generate(DinkyECS::World &world);
|
void generate(DinkyECS::World &world);
|
||||||
void randomize_entities(DinkyECS::World &world, components::GameConfig &config);
|
void randomize_entities(DinkyECS::World &world, components::GameConfig &config);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue