|
|
@ -53,9 +53,10 @@ void WorldBuilder::add_door(Room &room) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void WorldBuilder::partition_map(Room &cur, int depth) { |
|
|
|
void WorldBuilder::partition_map(Room &cur, int depth) { |
|
|
|
if(cur.width >= 5 && cur.width <= 10 && |
|
|
|
if(cur.width >= 3 && cur.width <= 6 && |
|
|
|
cur.height >= 5 && cur.height <= 10) { |
|
|
|
cur.height >= 3 && cur.height <= 6) |
|
|
|
$map.$rooms.push_back(cur); |
|
|
|
{ |
|
|
|
|
|
|
|
$map.add_room(cur); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -97,9 +98,11 @@ void WorldBuilder::update_door(Point &at, int wall_or_space) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void WorldBuilder::stylize_room(int room, string tile_name, float size) { |
|
|
|
void WorldBuilder::stylize_room(int room, string tile_name, float size) { |
|
|
|
Point center = $map.place_entity(room); |
|
|
|
Point pos_out; |
|
|
|
|
|
|
|
bool placed = $map.place_entity(room, pos_out); |
|
|
|
|
|
|
|
dbc::check(placed, "failed to place style in room"); |
|
|
|
|
|
|
|
|
|
|
|
for(matrix::circle it{$map.$walls, center, size}; it.next();) { |
|
|
|
for(matrix::circle it{$map.$walls, pos_out, size}; it.next();) { |
|
|
|
for(int x = it.left; x < it.right; x++) { |
|
|
|
for(int x = it.left; x < it.right; x++) { |
|
|
|
if(!$map.iswall(x, it.y)) { |
|
|
|
if(!$map.iswall(x, it.y)) { |
|
|
|
$map.$tiles.set_tile(x, it.y, tile_name); |
|
|
|
$map.$tiles.set_tile(x, it.y, tile_name); |
|
|
@ -108,22 +111,24 @@ void WorldBuilder::stylize_room(int room, string tile_name, float size) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void WorldBuilder::generate_map() { |
|
|
|
void WorldBuilder::generate_rooms() { |
|
|
|
PointList holes; |
|
|
|
|
|
|
|
Room root{ |
|
|
|
Room root{ |
|
|
|
.x = 0, |
|
|
|
.x = 0, |
|
|
|
.y = 0, |
|
|
|
.y = 0, |
|
|
|
.width = $map.$width, |
|
|
|
.width = $map.$width, |
|
|
|
.height = $map.$height |
|
|
|
.height = $map.$height |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// BUG: depth should be configurable
|
|
|
|
// BUG: depth should be configurable
|
|
|
|
partition_map(root, 10); |
|
|
|
partition_map(root, 10); |
|
|
|
|
|
|
|
|
|
|
|
place_rooms(); |
|
|
|
place_rooms(); |
|
|
|
|
|
|
|
|
|
|
|
dbc::check($map.room_count() > 0, "map generated zero rooms, map too small?"); |
|
|
|
dbc::check($map.room_count() > 0, "map generated zero rooms, map too small?"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void WorldBuilder::generate_map() { |
|
|
|
|
|
|
|
generate_rooms(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PointList holes; |
|
|
|
for(size_t i = 0; i < $map.$rooms.size() - 1; i++) { |
|
|
|
for(size_t i = 0; i < $map.$rooms.size() - 1; i++) { |
|
|
|
tunnel_doors(holes, $map.$rooms[i], $map.$rooms[i+1]); |
|
|
|
tunnel_doors(holes, $map.$rooms[i], $map.$rooms[i+1]); |
|
|
|
} |
|
|
|
} |
|
|
@ -133,14 +138,21 @@ void WorldBuilder::generate_map() { |
|
|
|
|
|
|
|
|
|
|
|
// place all the holes
|
|
|
|
// place all the holes
|
|
|
|
for(auto hole : holes) { |
|
|
|
for(auto hole : holes) { |
|
|
|
$map.$walls[hole.y][hole.x] = INV_SPACE; |
|
|
|
|
|
|
|
|
|
|
|
if(!matrix::inbounds($map.$walls, hole.x, hole.y)) { |
|
|
|
|
|
|
|
matrix::dump("MAP BEFORE CRASH", $map.$walls, hole.x, hole.y); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto err = fmt::format("invalid hold target {},{} map is only {},{}", |
|
|
|
|
|
|
|
hole.x, hole.y, matrix::width($map.$walls), |
|
|
|
|
|
|
|
matrix::height($map.$walls)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dbc::sentinel(err); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(matrix::each_cell it{$map.$walls}; it.next();) { |
|
|
|
$map.$walls[hole.y][hole.x] = INV_SPACE; |
|
|
|
int is_wall = !$map.$walls[it.y][it.x]; |
|
|
|
|
|
|
|
$map.$walls[it.y][it.x] = is_wall; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$map.invert_space(); |
|
|
|
$map.expand(); |
|
|
|
$map.expand(); |
|
|
|
$map.load_tiles(); |
|
|
|
$map.load_tiles(); |
|
|
|
|
|
|
|
|
|
|
@ -159,9 +171,11 @@ void WorldBuilder::generate_map() { |
|
|
|
DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string name, int in_room) { |
|
|
|
DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string name, int in_room) { |
|
|
|
auto &config = world.get_the<GameConfig>(); |
|
|
|
auto &config = world.get_the<GameConfig>(); |
|
|
|
auto item = world.entity(); |
|
|
|
auto item = world.entity(); |
|
|
|
auto pos = game_map.place_entity(in_room); |
|
|
|
Point pos_out; |
|
|
|
|
|
|
|
bool placed = game_map.place_entity(in_room, pos_out); |
|
|
|
|
|
|
|
dbc::check(placed, "failed to randomly place item in room"); |
|
|
|
json item_data = config.items[name]; |
|
|
|
json item_data = config.items[name]; |
|
|
|
world.set<Position>(item, {pos.x+1, pos.y+1}); |
|
|
|
world.set<Position>(item, {pos_out.x+1, pos_out.y+1}); |
|
|
|
|
|
|
|
|
|
|
|
if(item_data["inventory_count"] > 0) { |
|
|
|
if(item_data["inventory_count"] > 0) { |
|
|
|
world.set<InventoryItem>(item, {item_data["inventory_count"], item_data}); |
|
|
|
world.set<InventoryItem>(item, {item_data["inventory_count"], item_data}); |
|
|
@ -178,7 +192,9 @@ DinkyECS::Entity place_combatant(DinkyECS::World &world, Map &game_map, std::str |
|
|
|
auto &config = world.get_the<GameConfig>(); |
|
|
|
auto &config = world.get_the<GameConfig>(); |
|
|
|
auto enemy = world.entity(); |
|
|
|
auto enemy = world.entity(); |
|
|
|
auto enemy_data = config.enemies[name]; |
|
|
|
auto enemy_data = config.enemies[name]; |
|
|
|
auto pos = game_map.place_entity(in_room); |
|
|
|
Point pos; |
|
|
|
|
|
|
|
bool placed = game_map.place_entity(in_room, pos); |
|
|
|
|
|
|
|
dbc::check(placed, "failed to place combatant in room"); |
|
|
|
world.set<Position>(enemy, {pos}); |
|
|
|
world.set<Position>(enemy, {pos}); |
|
|
|
|
|
|
|
|
|
|
|
if(enemy_data.contains("components")) { |
|
|
|
if(enemy_data.contains("components")) { |
|
|
@ -250,11 +266,8 @@ void WorldBuilder::make_room(size_t origin_x, size_t origin_y, size_t w, size_t |
|
|
|
|
|
|
|
|
|
|
|
void WorldBuilder::place_rooms() { |
|
|
|
void WorldBuilder::place_rooms() { |
|
|
|
for(auto &cur : $map.$rooms) { |
|
|
|
for(auto &cur : $map.$rooms) { |
|
|
|
cur.x += WORLDBUILD_SHRINK; |
|
|
|
// println("ROOM x/y={},{}; w/h={},{}; map={},{}",
|
|
|
|
cur.y += WORLDBUILD_SHRINK; |
|
|
|
// cur.x, cur.y, cur.width, cur.height, $map.$width, $map.$height);
|
|
|
|
cur.width -= WORLDBUILD_SHRINK * 2; |
|
|
|
|
|
|
|
cur.height -= WORLDBUILD_SHRINK * 2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
add_door(cur); |
|
|
|
add_door(cur); |
|
|
|
make_room(cur.x, cur.y, cur.width, cur.height); |
|
|
|
make_room(cur.x, cur.y, cur.width, cur.height); |
|
|
|
} |
|
|
|
} |
|
|
@ -281,24 +294,34 @@ inline bool random_path(Map &map, PointList &holes, Point src, Point target) { |
|
|
|
return target_found; |
|
|
|
return target_found; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inline void straight_path(PointList &holes, Point src, Point target) { |
|
|
|
inline void straight_path(Map &map, PointList &holes, Point src, Point target) { |
|
|
|
for(matrix::line dig{src, target}; dig.next();) { |
|
|
|
for(matrix::line dig{src, target}; dig.next();) { |
|
|
|
holes.push_back({size_t(dig.x), size_t(dig.y)}); |
|
|
|
holes.push_back({size_t(dig.x), size_t(dig.y)}); |
|
|
|
holes.push_back({size_t(dig.x+1), size_t(dig.y)}); |
|
|
|
Point expand{(size_t)dig.x+1, (size_t)dig.y}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(map.inmap(expand.x, expand.y)) { |
|
|
|
|
|
|
|
// BUG? should really just move doors away from the edge
|
|
|
|
|
|
|
|
holes.push_back(expand); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void WorldBuilder::tunnel_doors(PointList &holes, Room &src, Room &target) { |
|
|
|
void WorldBuilder::tunnel_doors(PointList &holes, Room &src, Room &target) { |
|
|
|
int path_type = Random::uniform<int>(0, 3); |
|
|
|
int path_type = Random::uniform<int>(0, 3); |
|
|
|
|
|
|
|
|
|
|
|
switch(path_type) { |
|
|
|
switch(path_type) { |
|
|
|
case 0: |
|
|
|
case 0: |
|
|
|
// for now do 25% as simple straight paths
|
|
|
|
// for now do 25% as simple straight paths
|
|
|
|
straight_path(holes, src.exit, target.entry); |
|
|
|
straight_path($map, holes, src.exit, target.entry); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 1: |
|
|
|
|
|
|
|
// for now do 25% as simple straight paths
|
|
|
|
|
|
|
|
straight_path($map, holes, src.exit, target.entry); |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
// then do the rest as random with fallback
|
|
|
|
// then do the rest as random with fallback
|
|
|
|
if(!random_path($map, holes, src.exit, target.entry)) { |
|
|
|
if(!random_path($map, holes, src.exit, target.entry)) { |
|
|
|
straight_path(holes, src.exit, target.entry); |
|
|
|
straight_path($map, holes, src.exit, target.entry); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|