diff options
-rw-r--r-- | crawl-ref/source/dat/des/branches/shoals.des | 9 | ||||
-rw-r--r-- | crawl-ref/source/dgn-height.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/dgn-shoals.cc | 140 | ||||
-rw-r--r-- | crawl-ref/source/dgn-shoals.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 100 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 13 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 2 |
7 files changed, 227 insertions, 42 deletions
diff --git a/crawl-ref/source/dat/des/branches/shoals.des b/crawl-ref/source/dat/des/branches/shoals.des index b47761857f..2c9e38dbdd 100644 --- a/crawl-ref/source/dat/des/branches/shoals.des +++ b/crawl-ref/source/dat/des/branches/shoals.des @@ -546,7 +546,7 @@ ENDMAP # The hut itself may not contain Ilsuiw if she had other engagements. NAME: shoal_ilsuiw -TAGS: mini_float shoal_guardian +TAGS: shoal_guardian KMONS: 1 = Ilsuiw band, siren KMONS: 2 = merfolk impaler / merfolk javelineer SUBST: 3 = 33w @@ -567,13 +567,12 @@ ENDMAP # HangedMan's alternative Shoals:$ NAME: shoals_rune_alternative -TAGS: shoal_rune_hangedman water_ok allow_dup transparent mini_float +TAGS: shoal_rune_hangedman water_ok allow_dup transparent mini_float no_dump KMONS: 12 = merfolk impaler / merfolk javelineer / merfolk aquamancer KMONS: 3 = kraken / harpy band w:5 KMONS: d = siren / mermaid w:5 KITEM: d = barnacled rune of zot KFEAT: 123 = w -KFEAT: d = W KPROP: d = no_tide SHUFFLE: AB / AB / BA, CD / CD / DC NSUBST: 2 = 2 = 22w / * = 22www, 0 = 2:0 / * = 00... @@ -594,10 +593,8 @@ xxW...DC.x@ ENDMAP NAME: shoals_rune_alternative_decoy -TAGS: shoal_hut_hangedman water_ok allow_dup transparent mini_float +TAGS: shoal_hut_hangedman water_ok allow_dup transparent mini_float no_dump KMONS: 0 = 0 -KITEM: | = | -KFEAT: | = W SHUFFLE: AB / AB / BA, CD / CD / DC NSUBST: 0 = 3:0 / * = 00... SUBST: AC = x, B = w, D = . diff --git a/crawl-ref/source/dgn-height.cc b/crawl-ref/source/dgn-height.cc index a4390278d4..91092552ee 100644 --- a/crawl-ref/source/dgn-height.cc +++ b/crawl-ref/source/dgn-height.cc @@ -56,6 +56,9 @@ void dgn_island_centred_at(const coord_def &c, void dgn_smooth_height_at(coord_def c, int radius, int max_height) { + if (!in_bounds(c)) + return; + const int height = dgn_height_at(c); if (max_height != DGN_UNDEFINED_HEIGHT && height > max_height) return; diff --git a/crawl-ref/source/dgn-shoals.cc b/crawl-ref/source/dgn-shoals.cc index fae08d79b0..0447ff0f69 100644 --- a/crawl-ref/source/dgn-shoals.cc +++ b/crawl-ref/source/dgn-shoals.cc @@ -8,6 +8,7 @@ #include "dgn-shoals.h" #include "dgn-height.h" #include "env.h" +#include "flood_find.h" #include "fprop.h" #include "items.h" #include "itemprop.h" @@ -220,6 +221,22 @@ static void _shoals_apply_level() grd(*ri) = _shoals_feature_at(*ri); } +static void _shoals_postbuild_apply_level() +{ + for (rectangle_iterator ri(1); ri; ++ri) + { + if (!map_masked(*ri, MMT_VAULT)) + { + const dungeon_feature_type feat = grd(*ri); + if (feat_is_water(feat) || feat == DNGN_ROCK_WALL + || feat == DNGN_STONE_WALL || feat == DNGN_FLOOR) + { + grd(*ri) = _shoals_feature_at(*ri); + } + } + } +} + // Returns all points in deep water with an adjacent square in shallow water. static vector<coord_def> _shoals_water_depth_change_points() { @@ -288,22 +305,23 @@ static void _shoals_furniture(int margin) static void _shoals_deepen_edges() { - const int edge = 2; + const int edge = 1; + const int deepen_by = 1000; // Water of the edge of the screen is too deep to be exposed by tides. for (int y = 1; y < GYM - 2; ++y) { for (int x = 1; x <= edge; ++x) { - dgn_height_at(coord_def(x, y)) -= 800; - dgn_height_at(coord_def(GXM - 1 - x, y)) -= 800; + dgn_height_at(coord_def(x, y)) -= deepen_by; + dgn_height_at(coord_def(GXM - 1 - x, y)) -= deepen_by; } } for (int x = 1; x < GXM - 2; ++x) { for (int y = 1; y <= edge; ++y) { - dgn_height_at(coord_def(x, y)) -= 800; - dgn_height_at(coord_def(x, GYM - 1 - y)) -= 800; + dgn_height_at(coord_def(x, y)) -= deepen_by; + dgn_height_at(coord_def(x, GYM - 1 - y)) -= deepen_by; } } } @@ -700,6 +718,118 @@ void shoals_postprocess_level() shoals_apply_tides(0, true, false); } +static void _shoals_clamp_height_at(const coord_def &c, + int clamp_height = SHT_ROCK - 1) +{ + if (!in_bounds(c)) + return; + + if (dgn_height_at(c) > clamp_height) + dgn_height_at(c) = clamp_height; +} + +static void _shoals_connect_smooth_height_at(const coord_def &c) +{ + if (map_bounds_with_margin(c, 3)) + dgn_smooth_height_at(c, 1); +} + +static void _shoals_connecting_point_smooth(const coord_def &c, int radius) +{ + for (int dy = 0; dy < radius; ++dy) + { + for (int dx = 0; dx < radius; ++dx) + { + _shoals_connect_smooth_height_at(c + coord_def(dy, dx)); + if (dy) + _shoals_connect_smooth_height_at(c + coord_def(-dy, dx)); + if (dx) + _shoals_connect_smooth_height_at(c + coord_def(dy, -dx)); + if (dx && dy) + _shoals_connect_smooth_height_at(c + coord_def(-dy, -dx)); + } + } +} + +static void _shoals_connecting_point_clamp_height( + const coord_def &c, int radius) +{ + if (!in_bounds(c)) + return; + + for (rectangle_iterator ri(c - coord_def(radius, radius), + c + coord_def(radius, radius)); ri; ++ri) + { + _shoals_clamp_height_at(*ri); + } + + const int min_height_threshold = (SHT_SHALLOW_WATER + SHT_FLOOR) / 2; + if (dgn_height_at(c) < min_height_threshold) + dgn_height_at(c) = min_height_threshold; +} + +bool dgn_shoals_connect_point(const coord_def &point, + bool (*overwriteable)(dungeon_feature_type)) +{ + flood_find<feature_grid, coord_predicate> ff(env.grid, in_bounds, true, + false); + ff.add_feat(DNGN_FLOOR); + + const coord_def target = ff.find_first_from(point, env.level_map_mask); + if (!in_bounds(target)) + return false; + + const vector<coord_def> track = + dgn_join_the_dots_pathfind(point, target, MMT_VAULT); + + if (!track.empty()) + { + const int n_points = 15; + const int radius = 4; + + for (vector<coord_def>::const_iterator i = track.begin(); + i != track.end(); ++i) + { + int height = 0, npoints = 0; + for (radius_iterator ri(*i, radius, C_POINTY); ri; ++ri) + { + if (in_bounds(*ri)) + { + height += dgn_height_at(*ri); + ++npoints; + } + } + + const int target_height = SHT_FLOOR; + if (height < target_height) + { + const int elevation_change = target_height - height; + const int elevation_change_per_dot = + max(1, elevation_change / n_points + 1); + + dgn_island_centred_at(*i, n_points, radius, + int_range(elevation_change_per_dot, + elevation_change_per_dot + 20), + 3); + } + } + + for (int i = track.size() - 1; i >= 0; --i) + { + const coord_def &p(track[i]); + _shoals_connecting_point_smooth(p, radius + 2); + } + for (int i = track.size() - 1; i >= 0; --i) + { + const coord_def &p(track[i]); + _shoals_connecting_point_clamp_height(p, radius + 2); + } + + _shoals_postbuild_apply_level(); + } + return !track.empty(); +} + static void _shoals_run_tide(int &tide, int &acc) { // If someone is calling the tide, the tide velocity is clamped high. diff --git a/crawl-ref/source/dgn-shoals.h b/crawl-ref/source/dgn-shoals.h index 24e17da41a..62c04ecd3f 100644 --- a/crawl-ref/source/dgn-shoals.h +++ b/crawl-ref/source/dgn-shoals.h @@ -3,6 +3,8 @@ void dgn_build_shoals_level(); void dgn_shoals_generate_flora(); +bool dgn_shoals_connect_point(const coord_def &point, + bool (*overwriteable)(dungeon_feature_type)); void shoals_postprocess_level(); void shoals_apply_tides(int turns_elapsed, bool force, bool incremental_tide); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 2e4b6d8f8b..00ea7ced85 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -117,7 +117,9 @@ static void _add_plant_clumps(int frequency = 10, int clump_density = 12, static void _pick_float_exits(vault_placement &place, vector<coord_def> &targets); -static bool _connect_spotty(const coord_def& from); +static bool _feat_is_wall_floor_liquid(dungeon_feature_type); +static bool _connect_spotty(const coord_def& from, + bool (*overwriteable)(dungeon_feature_type) = NULL); static bool _connect_vault_exit(const coord_def& exit); // ITEM & SHOP FUNCTIONS @@ -2259,7 +2261,7 @@ static void _build_dungeon_level(dungeon_feature_type dest_stairs_type) const unsigned nvaults = env.level_vaults.size(); // Any further vaults must make sure not to disrupt level layout. - dgn_check_connectivity = !player_in_branch(BRANCH_SHOALS); + dgn_check_connectivity = true; if (player_in_branch(BRANCH_MAIN_DUNGEON) && !crawl_state.game_is_tutorial()) @@ -3966,8 +3968,7 @@ _build_vault_impl(const map_def *vault, if (!make_no_exits) { const bool spotty = player_in_branch(BRANCH_ORCISH_MINES) - || player_in_branch(BRANCH_SLIME_PITS) - || player_in_branch(BRANCH_SHOALS); + || player_in_branch(BRANCH_SLIME_PITS); place.connect(spotty); } @@ -5003,10 +5004,16 @@ static void _jtd_init_surrounds(coord_set &coords, uint32_t mapmask, } } -static bool _join_the_dots_pathfind(coord_set &coords, - const coord_def &from, const coord_def &to, - uint32_t mapmask) +// Resets travel_point_distance +vector<coord_def> dgn_join_the_dots_pathfind(const coord_def &from, + const coord_def &to, + uint32_t mapmask) { + memset(travel_point_distance, 0, sizeof(travel_distance_grid_t)); + const coord_comparator comp(to); + coord_set coords(comp); + + vector<coord_def> path; coord_def curr = from; while (true) { @@ -5026,36 +5033,44 @@ static bool _join_the_dots_pathfind(coord_set &coords, } if (curr != to) - return false; + return path; while (curr != from) { if (!map_masked(curr, mapmask)) - { - grd(curr) = DNGN_FLOOR; - dgn_height_set_at(curr); - } + path.push_back(curr); const int dist = travel_point_distance[curr.x][curr.y]; ASSERT(dist < 0 && dist != -1000); curr += coord_def(-dist / 4 - 2, (-dist % 4) - 2); } if (!map_masked(curr, mapmask)) - grd(curr) = DNGN_FLOOR; + path.push_back(curr); - return true; + return path; } bool join_the_dots(const coord_def &from, const coord_def &to, - uint32_t mapmask) + uint32_t mapmask, + bool (*overwriteable)(dungeon_feature_type)) { - memset(travel_point_distance, 0, sizeof(travel_distance_grid_t)); + if (!overwriteable) + overwriteable = _feat_is_wall_floor_liquid; - const coord_comparator comp(to); - coord_set coords(comp); - const bool found = _join_the_dots_pathfind(coords, from, to, mapmask); + const vector<coord_def> path = + dgn_join_the_dots_pathfind(from, to, mapmask); - return found; + for (vector<coord_def>::const_iterator i = path.begin(); i != path.end(); + ++i) + { + if (!map_masked(*i, mapmask) && overwriteable(grd(*i))) + { + grd(*i) = DNGN_FLOOR; + dgn_height_set_at(*i); + } + } + + return !path.empty() || from == to; } static dungeon_feature_type _pick_temple_altar(vault_placement &place) @@ -5449,17 +5464,28 @@ static bool _spotty_seed_ok(const coord_def& p) && p.x < GXM - margin && p.y < GYM - margin); } +static bool _feat_is_wall_floor_liquid(dungeon_feature_type feat) +{ + return (feat_is_water(feat) || feat_is_lava(feat) || feat_is_wall(feat) + || feat == DNGN_FLOOR); +} + // Connect vault exit "from" to dungeon floor by growing a spotty chamber. // This tries to be like _spotty_level, but probably isn't quite. // It might be better to aim for a more open connection -- currently // it stops pretty much as soon as connectivity is attained. -static bool _connect_spotty(const coord_def& from) +set<coord_def> +dgn_spotty_connect_path(const coord_def& from, + bool (*overwriteable)(dungeon_feature_type)) { set<coord_def> flatten; set<coord_def> border; set<coord_def>::const_iterator it; bool success = false; + if (!overwriteable) + overwriteable = _feat_is_wall_floor_liquid; + for (adjacent_iterator ai(from); ai; ++ai) if (!map_masked(*ai, MMT_VAULT) && _spotty_seed_ok(*ai)) border.insert(*ai); @@ -5483,11 +5509,8 @@ static bool _connect_spotty(const coord_def& from) if (grd(*ai) == DNGN_FLOOR) success = true; // Through, but let's remove the others, too. - if ((grd(*ai) != DNGN_ROCK_WALL && grd(*ai) != DNGN_SLIMY_WALL) - || flatten.find(*ai) != flatten.end()) - { + if (!overwriteable(grd(*ai)) || flatten.find(*ai) != flatten.end()) continue; - } flatten.insert(*ai); for (adjacent_iterator bi(*ai); bi; ++bi) @@ -5502,16 +5525,29 @@ static bool _connect_spotty(const coord_def& from) } } - if (success) + if (!success) + flatten.clear(); + + return flatten; +} + +static bool _connect_spotty(const coord_def& from, + bool (*overwriteable)(dungeon_feature_type)) +{ + const set<coord_def> spotty_path = + dgn_spotty_connect_path(from, overwriteable); + + if (!spotty_path.empty()) { - for (it = flatten.begin(); it != flatten.end(); ++it) + for (set<coord_def>::const_iterator it = spotty_path.begin(); + it != spotty_path.end(); ++it) { grd(*it) = DNGN_FLOOR; dgn_height_set_at(*it); } } - return success; + return !spotty_path.empty(); } bool place_specific_trap(const coord_def& where, trap_type spec_type, int charges) @@ -6442,9 +6478,15 @@ void vault_placement::connect(bool spotty) const for (vector<coord_def>::const_iterator i = exits.begin(); i != exits.end(); ++i) { - if (spotty && _connect_spotty(*i)) + if (spotty && _connect_spotty(*i, _feat_is_wall_floor_liquid)) continue; + if (player_in_branch(BRANCH_SHOALS) && + dgn_shoals_connect_point(*i, _feat_is_wall_floor_liquid)) + { + continue; + } + if (!_connect_vault_exit(*i)) dprf("Warning: failed to connect vault exit (%d;%d).", i->x, i->y); } diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 298072e80a..3f485aac26 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -285,7 +285,18 @@ string dump_vault_maps(); bool dgn_square_travel_ok(const coord_def &c); -bool join_the_dots(const coord_def &from, const coord_def &to, unsigned mmask); +set<coord_def> dgn_spotty_connect_path( + const coord_def& from, + bool (*overwriteable)(dungeon_feature_type) = NULL); + +// Resets travel_point_distance! +vector<coord_def> dgn_join_the_dots_pathfind(const coord_def &from, + const coord_def &to, + uint32_t mapmask); + +bool join_the_dots(const coord_def &from, const coord_def &to, + unsigned mmask, + bool (*overwriteable)(dungeon_feature_type) = NULL); int count_feature_in_box(int x0, int y0, int x1, int y1, dungeon_feature_type feat); bool door_vetoed(const coord_def pos); diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index cbf04210ec..a2f6df14cf 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -508,7 +508,7 @@ static coord_def _find_minivault_place( // [ds] The margin around the edges of the map where the minivault // won't be placed. Purely arbitrary as far as I can see. - const int margin = MAPGEN_BORDER * 2; + const int margin = MAPGEN_BORDER * 2 + 1; // Find a target area which can be safely overwritten. for (int tries = 0; tries < 600; ++tries) |