diff options
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/acr.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/arena.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/ziggurat.lua | 9 | ||||
-rw-r--r-- | crawl-ref/source/decks.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 253 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 35 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 200 | ||||
-rw-r--r-- | crawl-ref/source/maps.h | 12 | ||||
-rw-r--r-- | crawl-ref/source/stuff.h | 7 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 2 |
11 files changed, 221 insertions, 312 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 1f4e2e528c..daf8dc2c49 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -815,7 +815,7 @@ static void _do_wizard_command(int wiz_command, bool silent_fail) if (dst.empty()) dst = "bazaar"; - if (!find_map_by_name(dst) && !random_map_for_tag(dst, false)) + if (!find_map_by_name(dst) && !random_map_for_tag(dst)) { mprf("No map named '%s' or tagged '%s'.", dst.c_str(), dst.c_str()); diff --git a/crawl-ref/source/arena.cc b/crawl-ref/source/arena.cc index 34aed4a9e3..f9f5752cd9 100644 --- a/crawl-ref/source/arena.cc +++ b/crawl-ref/source/arena.cc @@ -174,7 +174,7 @@ namespace arena const unwind_stringset mnames(you.uniq_map_names); std::string map_name = "arena_" + arena_type; - const map_def *map = random_map_for_tag(map_name.c_str(), false); + const map_def *map = random_map_for_tag(map_name.c_str()); if (!map) throw make_stringf("No arena maps named \"%s\"", arena_type.c_str()); diff --git a/crawl-ref/source/dat/clua/ziggurat.lua b/crawl-ref/source/dat/clua/ziggurat.lua index a022da3c27..d25e194ce1 100644 --- a/crawl-ref/source/dat/clua/ziggurat.lua +++ b/crawl-ref/source/dat/clua/ziggurat.lua @@ -452,8 +452,7 @@ local function ziggurat_create_loot_vault(entry, exit) end local connect_point = exit - inc * 3 - - local map = dgn.map_by_tag("ziggurat_loot_chamber", false) + local map = dgn.map_by_tag("ziggurat_loot_chamber") if not map then return exit @@ -467,7 +466,7 @@ local function ziggurat_create_loot_vault(entry, exit) return res end - local function bad_loot_bounds(map, px, py, xs, ys) + local function good_loot_bounds(map, px, py, xs, ys) local vc = dgn.point(px + math.floor(xs / 2), py + math.floor(ys / 2)) @@ -485,11 +484,11 @@ local function ziggurat_create_loot_vault(entry, exit) local linc = (exit - vc):sgn() -- The map's positions should be at the same increment to the exit -- as the exit is to the entrance, else reject the place. - return not (inc == linc) or not safe_area() + return (inc == linc) and safe_area() end local function connect_loot_chamber() - return dgn.with_map_bounds_fn(bad_loot_bounds, place_loot_chamber) + return dgn.with_map_bounds_fn(good_loot_bounds, place_loot_chamber) end local res = dgn.with_map_anchors(connect_point.x, connect_point.y, diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index b427f6eee2..d95cb0dc4c 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -2454,7 +2454,7 @@ static bool _trowel_card(int power, deck_rarity_type rarity) if (power_level >= 2) { // Generate a portal to something. - const map_def *map = random_map_for_tag("trowel_portal", false, false); + const map_def *map = random_map_for_tag("trowel_portal", false); if (!map) { mpr("A buggy portal flickers into view, then vanishes."); diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index e88dde53da..0b22bfc034 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -197,17 +197,12 @@ static bool _build_vaults(int level_number, bool check_collisions = false, bool make_no_exits = false, const coord_def &where = coord_def(-1, -1)); -static bool _build_minivaults(int level_number, - const map_def *vault, - bool clobber = false, - bool make_no_exits = false, - const coord_def &where = coord_def() ); static void _vault_grid( vault_placement &, int vgrid, const coord_def& where, bool recursive = false); -static const map_def *_dgn_random_map_for_place(bool wantmini); +static const map_def *_dgn_random_map_for_place(); static void _dgn_load_colour_grid(); static void _dgn_map_colour_fixup(); @@ -2063,22 +2058,21 @@ static void _prepare_shoals(int level_number) grd[centres[j].x-1][centres[j].y] = DNGN_STONE_STAIRS_UP_III; // Place the rune - const map_def *vault = random_map_for_tag("shoal_rune", true); - - _build_minivaults( level_number, vault, false, false, - centres[1] ); + const map_def *vault = random_map_for_tag("shoal_rune"); + _build_secondary_vault(level_number, vault, -1, false, false, + centres[1]); for ( int i = 2; i < num_islands; ++i ) { // Place (non-rune) minivaults on the other islands do { - vault = _dgn_random_map_for_place(true); + vault = _dgn_random_map_for_place(); } while ( !vault ); - _build_minivaults( level_number, vault, false, false, - centres[i] ); + _build_secondary_vault(level_number, vault, -1, false, false, + centres[i]); } } else @@ -2309,7 +2303,7 @@ static builder_rc_type _builder_by_type(int level_number, char level_type) const map_def *vault = random_map_for_tag("pan", true); ASSERT( vault ); - _build_minivaults(level_number, vault); + _build_secondary_vault(level_number, vault); } return BUILD_SKIP; @@ -2331,7 +2325,7 @@ static void _portal_vault_level(int level_number) const char* level_name = trimmed_name.c_str(); - const map_def *vault = random_map_for_place(level_id::current(), false); + const map_def *vault = random_map_for_place(level_id::current()); #ifdef WIZARD if (!vault && you.wizard && map_count_for_tag(level_name, false) > 1) @@ -2396,7 +2390,7 @@ static void _portal_vault_level(int level_number) static const map_def *_random_portal_vault(const std::string &tag) { - return random_map_for_tag(tag, false, true); + return random_map_for_tag(tag, true); } static bool _place_portal_vault(int stair, const std::string &tag, int dlevel) @@ -2408,17 +2402,17 @@ static bool _place_portal_vault(int stair, const std::string &tag, int dlevel) return _build_secondary_vault(dlevel, vault, stair); } -static const map_def *_dgn_random_map_for_place(bool wantmini) +static const map_def *_dgn_random_map_for_place() { const level_id lid = level_id::current(); - const map_def *vault = random_map_for_place(lid, wantmini); + const map_def *vault = random_map_for_place(lid); // Disallow entry vaults for tutorial (only complicates things). if (!vault && lid.branch == BRANCH_MAIN_DUNGEON && lid.depth == 1 && !Options.tutorial_left) { - vault = random_map_for_tag("entry", wantmini); + vault = random_map_for_tag("entry"); } return (vault); @@ -2429,7 +2423,7 @@ static const map_def *_dgn_random_map_for_place(bool wantmini) // otherwise. static builder_rc_type _builder_by_branch(int level_number) { - const map_def *vault = _dgn_random_map_for_place(false); + const map_def *vault = _dgn_random_map_for_place(); if (vault) { @@ -2478,7 +2472,7 @@ static void _place_minivaults(const std::string &tag, int lo, int hi, if (!vault) return; - _build_minivaults(you.your_level, vault); + _build_secondary_vault(you.your_level, vault); } return; } @@ -2490,20 +2484,9 @@ static void _place_minivaults(const std::string &tag, int lo, int hi, { vault = random_map_in_depth(level_id::current(), true); if (vault) - _build_minivaults(you.your_level, vault); + _build_secondary_vault(you.your_level, vault); } while (vault && vault->has_tag("extra")); } - - int chance = you.your_level == 0? 50 : 100; - while (chance && x_chance_in_y(chance, 100) || nvaults-- > 0) - { - const map_def *vault = _dgn_random_map_for_place(true); - if (!vault) - break; - - _build_minivaults(you.your_level, vault); - chance /= 4; - } } // Returns 1 if we should dispense with city building, @@ -2515,7 +2498,7 @@ static builder_rc_type _builder_normal(int level_number, char level_type, UNUSED( level_type ); bool skipped = false; - const map_def *vault = _dgn_random_map_for_place(false); + const map_def *vault = _dgn_random_map_for_place(); // Can't have vaults on you.where_are_you != BRANCH_MAIN_DUNGEON levels. if (!vault && use_random_maps && can_create_vault) @@ -2613,7 +2596,7 @@ static builder_rc_type _builder_normal(int level_number, char level_type, if (!sr.created && one_chance_in(5)) #endif { - const map_def *sroom = random_map_for_tag("special_room", true, true); + const map_def *sroom = random_map_for_tag("special_room", true); // Might not be any special room definitions appropriate for // this branch and depth. @@ -2904,11 +2887,6 @@ static void _place_extra_vaults() && can_create_vault) { const map_def *vault = random_map_in_depth(level_id::current()); - - // ORIENT: encompass maps are unsuitable as secondary vaults. - if (vault && vault->orient == MAP_ENCOMPASS) - vault = NULL; - if (vault && _build_secondary_vault(you.your_level, vault, -1)) { const map_def &map(*vault); @@ -3636,35 +3614,13 @@ static void _special_room(int level_number, spec_room &sr, lua_special_room_spec = sr; lua_special_room_level = level_number; - _build_minivaults( level_number, vault, false, false, sr.tl); + _build_secondary_vault( level_number, vault, -1, false, false, sr.tl); lua_special_room_spec.created = false; lua_special_room_spec.tl.set(-1, -1); lua_special_room_level = -1; } // end special_room() -// Used for placement of vaults. -static bool _may_overwrite_feature(const dungeon_feature_type grid, - bool water_ok, bool rock_ok = true) -{ - // Floor, and closed/secret doors may always be overwritten. - if (grid == DNGN_FLOOR - || grid == DNGN_CLOSED_DOOR || grid == DNGN_SECRET_DOOR) - { - return (true); - } - - if (grid == DNGN_ROCK_WALL) - return (rock_ok); - - // Watery grids may be overwritten if water_ok == true. - if (grid == DNGN_DEEP_WATER || grid == DNGN_SHALLOW_WATER) - return (water_ok); - - // Otherwise, don't overwrite this feature. - return (false); -} - // Used for placement of rivers/lakes. static bool _may_overwrite_pos(const int i, const int j) { @@ -3682,134 +3638,6 @@ static bool _may_overwrite_pos(const int i, const int j) return (mgrd[i][j] == NON_MONSTER && igrd[i][j] == NON_ITEM); } -static bool _safe_minivault_place(int v1x, int v1y, - const vault_placement &place, - bool clobber) -{ - if (clobber) - return (true); - - const bool water_ok = place.map.has_tag("water_ok"); - const std::vector<std::string> &lines = place.map.map.get_lines(); - for (int vx = v1x; vx < v1x + place.size.x; vx++) - for (int vy = v1y; vy < v1y + place.size.y; vy++) - { - if (lines[vy - v1y][vx - v1x] == ' ') - continue; - - if (dgn_Map_Mask[vx][vy]) - return (false); - - const dungeon_feature_type dfeat = grd[vx][vy]; - - // Don't overwrite features other than floor, rock wall, doors, - // nor water, if !water_ok. - if (!_may_overwrite_feature(dfeat, water_ok)) - return (false); - - // Don't overwrite items or monsters, either! - if (igrd[vx][vy] != NON_ITEM || mgrd[vx][vy] != NON_MONSTER) - return (false); - } - - return (true); -} - -static bool _connected_minivault_place(int v1x, int v1y, - const vault_placement &place) -{ - // Must not be completely isolated. - const bool water_ok = place.map.has_tag("water_ok"); - const std::vector<std::string> &lines = place.map.map.get_lines(); - - for (int vx = v1x; vx < v1x + place.size.x; vx++) - for (int vy = v1y; vy < v1y + place.size.y; vy++) - { - if (lines[vy - v1y][vx - v1x] == ' ') - continue; - - // Overwrite floor, doors or water, but not rock walls. - if (_may_overwrite_feature(grd[vx][vy], water_ok, false)) - return (true); - } - - return (false); -} - -static bool _find_minivault_place(const vault_placement &place, - coord_def& v1, bool clobber) -{ - // [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; - - // Find a target area which can be safely overwritten. - for (int tries = 0; tries < 600; ++tries) - { - v1.x = random_range( margin, GXM - margin - place.size.x ); - v1.y = random_range( margin, GYM - margin - place.size.y ); - - if (!_safe_minivault_place( v1.x, v1.y, place, clobber )) - continue; - - if (_connected_minivault_place(v1.x, v1.y, place)) - return (true); - } - return (false); -} - -static bool _build_minivaults(int level_number, const map_def *vault, - bool clobber, bool make_no_exits, - const coord_def &where) -{ - if (dgn_check_connectivity && !dgn_zones) - dgn_zones = _dgn_count_disconnected_zones(false); - - vault_placement place; - - place.level_number = level_number; - vault_main(place, vault); - - coord_def v1; - - // Not map_bounds, minivaults should never touch edge. - if (in_bounds(where)) - { - coord_def tl(where - place.size / 2); - fit_region_into_map_bounds(tl, place.size, 1); - v1 = tl; - } - else if (!_find_minivault_place(place, v1, clobber)) - return (false); - - place.pos = v1; - - Level_Vaults.push_back(place); - -#ifdef DEBUG_DIAGNOSTICS - if (crawl_state.map_stat_gen) - mapgen_report_map_use(place.map); -#endif - - dgn_register_place(place, true); - - place.apply_grid(); - - if (!make_no_exits) - { - // This is a throwaway. - std::vector<coord_def> &target_connections = place.exits; - - if (target_connections.empty() && place.map.has_tag("mini_float")) - _pick_float_exits(place, target_connections); - - if (!target_connections.empty()) - _connect_vault(place); - } - - return (true); -} // end build_minivaults() - static void _build_rooms(const dgn_region_list &excluded, const std::vector<coord_def> &connections_needed, int nrooms) @@ -4237,19 +4065,11 @@ bool dgn_place_map(const map_def *mdef, bool clobber, bool make_no_exits, } } - if (mdef->is_minivault()) - { - did_map = _build_minivaults(you.your_level, mdef, clobber, - make_no_exits, where); - } - else - { - dungeon_feature_type rune_subst = DNGN_FLOOR; - if (mdef->has_tag_suffix("_entry")) - rune_subst = _dgn_find_rune_subst_tags(mdef->tags); - did_map = _build_secondary_vault(you.your_level, mdef, rune_subst, - clobber, make_no_exits, where); - } + dungeon_feature_type rune_subst = DNGN_FLOOR; + if (mdef->has_tag_suffix("_entry")) + rune_subst = _dgn_find_rune_subst_tags(mdef->tags); + did_map = _build_secondary_vault(you.your_level, mdef, rune_subst, + clobber, make_no_exits, where); // Activate any markers within the map. if (did_map && !Generating_Level) @@ -4279,7 +4099,11 @@ static bool _build_secondary_vault(int level_number, const map_def *vault, int rune_subst, bool clobber, bool no_exits, const coord_def &where) { - dgn_zones = _dgn_count_disconnected_zones(false); + // Don't waste time trying to place encompass vaults as + // secondaries. + if (vault->orient == MAP_ENCOMPASS) + return (false); + if (_build_vaults(level_number, vault, rune_subst, true, !clobber, no_exits, where)) { @@ -4312,15 +4136,18 @@ static bool _build_vaults(int level_number, const map_def *vault, const int gluggy = vault_main(place, vault, check_collisions); - if (gluggy == MAP_NONE || !gluggy) + if (gluggy == MAP_NONE) return (false); place.apply_grid(); dgn_register_place(place, true); std::vector<coord_def> &target_connections = place.exits; - if (target_connections.empty() && gluggy != MAP_ENCOMPASS) + if (target_connections.empty() && gluggy != MAP_ENCOMPASS + && (!place.map.is_minivault() || place.map.has_tag("mini_float"))) + { _pick_float_exits(place, target_connections); + } if (make_no_exits) target_connections.clear(); @@ -6567,12 +6394,12 @@ static void _place_extra_lab_minivaults(int level_number) std::set<const map_def*> vaults_used; while (true) { - const map_def *vault = random_map_for_tag("lab", true, false); + const map_def *vault = random_map_for_tag("lab", false); if (!vault || vaults_used.find(vault) != vaults_used.end()) break; vaults_used.insert(vault); - if (!_build_minivaults(level_number, vault)) + if (!_build_secondary_vault(level_number, vault)) break; } } @@ -6837,7 +6664,7 @@ static void _labyrinth_level(int level_number) GYM - LABYRINTH_BORDER - 1 ); // First decide if we're going to use a Lab minivault. - const map_def *vault = random_map_for_tag("minotaur", true, false); + const map_def *vault = random_map_for_tag("minotaur", false); vault_placement place; if (vault) @@ -6846,7 +6673,7 @@ static void _labyrinth_level(int level_number) coord_def end; _labyrinth_build_maze(end, lab); - if (!vault || !_build_minivaults(level_number, vault)) + if (!vault || !_build_secondary_vault(level_number, vault)) { vault = NULL; _labyrinth_place_exit(end); @@ -7473,10 +7300,10 @@ static void _roguey_level(int level_number, spec_room &sr, bool make_stairs) const map_def *sroom; #ifdef DEBUG_SPECIAL_ROOMS - if ((sroom = random_map_for_tag("special_room", true, true)) != NULL) + if ((sroom = random_map_for_tag("special_room", true)) != NULL) #else if (one_chance_in(10) - && (sroom = random_map_for_tag("special_room", true, true)) != NULL) + && (sroom = random_map_for_tag("special_room", true)) != NULL) #endif { int spec_room_done = random2(25); diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index b85a67d5f7..1f5ac68b53 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -2378,10 +2378,11 @@ static int dgn_create_monster(lua_State *ls) for (int i = 0, size = mlist.size(); i < size; ++i) { mons_spec mspec = mlist.get_monster(i); - if (dgn_place_monster(mspec, you.your_level, c, - false, false, false)) + const int mid = dgn_place_monster(mspec, you.your_level, c, + false, false, false); + if (mid != -1) { - push_monster(ls, &menv[mgrd(c)]); + push_monster(ls, &menv[mid]); return (1); } } @@ -2418,23 +2419,23 @@ static int dgn_create_item(lua_State *ls) return (0); } -static std::auto_ptr<lua_datum> _dgn_map_bad_bounds_fn; +static std::auto_ptr<lua_datum> _dgn_map_safe_bounds_fn; -static bool _lua_map_place_invalid(const map_def &map, - const coord_def &c, - const coord_def &size) +static bool _lua_map_place_valid(const map_def &map, + const coord_def &c, + const coord_def &size) { #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "lua_map_place_invalid: (%d,%d) (%d,%d)", c.x, c.y, size.x, size.y); #endif - lua_stack_cleaner clean(_dgn_map_bad_bounds_fn->lua); + lua_stack_cleaner clean(_dgn_map_safe_bounds_fn->lua); // Push the Lua function onto the stack. - _dgn_map_bad_bounds_fn->push(); + _dgn_map_safe_bounds_fn->push(); - lua_State *ls = _dgn_map_bad_bounds_fn->lua; + lua_State *ls = _dgn_map_safe_bounds_fn->lua; // Push map, pos.x, pos.y, size.x, size.y clua_push_map(ls, const_cast<map_def*>(&map)); @@ -2459,12 +2460,12 @@ LUAFN(dgn_with_map_bounds_fn) if (lua_gettop(ls) != 2 || !lua_isfunction(ls, 1) || !lua_isfunction(ls, 2)) luaL_error(ls, "Expected map-bounds check fn and action fn."); - _dgn_map_bad_bounds_fn.reset(new lua_datum(vm, 1, false)); + _dgn_map_safe_bounds_fn.reset(new lua_datum(vm, 1, false)); int err = 0; { - unwind_var<map_place_check_t> mpc(map_place_invalid, - _lua_map_place_invalid); + unwind_var<map_place_check_t> mpc(map_place_valid, + _lua_map_place_valid); // All set, call our friend, the second function. ASSERT(lua_isfunction(ls, -1)); @@ -2476,7 +2477,7 @@ LUAFN(dgn_with_map_bounds_fn) // happen when lua_call does its longjmp. err = lua_pcall(ls, 0, 1, 0); - _dgn_map_bad_bounds_fn.reset(NULL); + _dgn_map_safe_bounds_fn.reset(NULL); } if (err) @@ -2670,9 +2671,8 @@ LUAFN(dgn_map_by_tag) { if (const char *tag = luaL_checkstring(ls, 1)) { - const bool mini = _lua_boolean(ls, 2, true); const bool check_depth = _lua_boolean(ls, 3, true); - return _lua_push_map(ls, random_map_for_tag(tag, mini, check_depth)); + return _lua_push_map(ls, random_map_for_tag(tag, check_depth)); } return (0); } @@ -2687,8 +2687,7 @@ LUAFN(dgn_map_in_depth) LUAFN(dgn_map_by_place) { const level_id lid = _lua_level_id(ls, 1); - const bool mini = _lua_boolean(ls, 2, true); - return _lua_push_map(ls, random_map_for_place(lid, mini)); + return _lua_push_map(ls, random_map_for_place(lid)); } LUAFN(_dgn_place_map) diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index b8c48bccb9..21b26518a4 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -1590,7 +1590,7 @@ bool map_def::has_depth() const bool map_def::is_minivault() const { - return (orient == MAP_NONE); + return (has_tag("minivault")); } // Tries to dock a floating vault - push it to one edge of the level. @@ -1848,6 +1848,13 @@ std::string map_def::resolve() void map_def::fixup() { normalise(); + + // Fixup minivaults into floating vaults tagged "minivault". + if (orient == MAP_NONE) + { + orient = MAP_FLOAT; + tags += " minivault"; + } } bool map_def::has_tag(const std::string &tagwanted) const diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 1e35bed17e..0f1d37acb2 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -30,8 +30,9 @@ #include "stuff.h" #include "terrain.h" -static bool bad_map_place(const map_def &map, const coord_def &c, - const coord_def &size); +static bool _safe_vault_place(const map_def &md, + const coord_def &c, + const coord_def &size); static int write_vault(map_def &mdef, vault_placement &, @@ -46,7 +47,7 @@ static bool resolve_map(map_def &def); // Globals: Use unwind_var to modify! // Checks whether a map place is valid. -map_place_check_t map_place_invalid = bad_map_place; +map_place_check_t map_place_valid = _safe_vault_place; // If non-empty, any floating vault's @ exit must land on these point. point_vector map_anchor_points; @@ -66,8 +67,7 @@ static map_vector vdefs; // Make sure that vault_n, where n is a number, is a vault which can be put // anywhere, while other vault names are for specific level ranges, etc. -int vault_main( vault_placement &place, - const map_def *vault, +int vault_main( vault_placement &place, const map_def *vault, bool check_place) { #ifdef DEBUG_DIAGNOSTICS @@ -78,9 +78,9 @@ int vault_main( vault_placement &place, mapgen_report_map_try(*vault); #endif - // Return value of zero forces dungeon.cc to regenerate the level, except - // for branch entry vaults where dungeon.cc just rejects the vault and - // places a vanilla entry. + // Return value of MAP_NONE forces dungeon.cc to regenerate the + // level, except for branch entry vaults where dungeon.cc just + // rejects the vault and places a vanilla entry. return (write_vault( const_cast<map_def&>(*vault), place, check_place )); } @@ -155,46 +155,6 @@ static bool resolve_map(map_def &map) return (true); } -// Determines if the region specified by (x, y, x + width - 1, y + height - 1) -// is a bad place to build a vault. -static bool bad_map_place(const map_def &map, const coord_def &c, - const coord_def &size) -{ - const std::vector<std::string> &lines = map.map.get_lines(); - for (rectangle_iterator r(c, c + size - 1); r; ++r) - { - const coord_def &p(*r); - const coord_def dp = p - c; - if (lines[dp.y][dp.x] == ' ') - continue; - - if (dgn_Map_Mask[p.x][p.y]) - return (true); - - if (igrd(p) != NON_ITEM || mgrd(p) != NON_MONSTER) - return (true); - - const dungeon_feature_type grid = grd(p); - - if (!grid_is_opaque(grid) - && grid != DNGN_FLOOR - && grid != DNGN_SHALLOW_WATER - && grid != DNGN_CLOSED_DOOR - && grid != DNGN_OPEN_DOOR - && grid != DNGN_SECRET_DOOR) - { -#ifdef DEBUG_DIAGNOSTICS - mprf(MSGCH_DIAGNOSTICS, - "Rejecting place because of %s at (%d,%d)", - dungeon_feature_name(grid), p.x, p.y); -#endif - return (true); - } - } - - return (false); -} - void fit_region_into_map_bounds(coord_def &pos, const coord_def &size, int margin) { @@ -215,6 +175,115 @@ void fit_region_into_map_bounds(coord_def &pos, const coord_def &size, pos.y = Y_2 - size.y + 1; } +// Used for placement of vaults. +static bool _may_overwrite_feature(const dungeon_feature_type grid, + bool water_ok, bool wall_ok = true) +{ + // Deep water grids may be overwritten if water_ok == true. + if (grid == DNGN_DEEP_WATER) + return (water_ok); + + // Handle all other non-LOS blocking grids here. + if (!grid_is_opaque(grid) + && grid != DNGN_FLOOR + && grid != DNGN_SHALLOW_WATER + && grid != DNGN_CLOSED_DOOR + && grid != DNGN_OPEN_DOOR + && grid != DNGN_SECRET_DOOR) + { + return (false); + } + + if (grid_is_wall(grid)) + return (wall_ok); + + // Otherwise, feel free to clobber this feature. + return (true); +} + +static bool _safe_vault_place(const map_def &map, + const coord_def &c, + const coord_def &size) +{ + if (size.zero()) + return (true); + + const bool water_ok = map.has_tag("water_ok"); + const std::vector<std::string> &lines = map.map.get_lines(); + + for (rectangle_iterator ri(c, c + size - 1); ri; ++ri) + { + const coord_def &cp(*ri); + const coord_def &dp(cp - c); + + if (lines[dp.y][dp.x] == ' ') + continue; + + if (dgn_Map_Mask[cp.x][cp.y]) + return (false); + + const dungeon_feature_type dfeat = grd(cp); + + // Don't overwrite features other than floor, rock wall, doors, + // nor water, if !water_ok. + if (!_may_overwrite_feature(dfeat, water_ok)) + return (false); + + // Don't overwrite items or monsters, either! + if (igrd(cp) != NON_ITEM || mgrd(cp) != NON_MONSTER) + return (false); + } + + return (true); +} + +static bool _connected_minivault_place(const coord_def &c, + const vault_placement &place) +{ + if (place.size.zero()) + return (true); + + // Must not be completely isolated. + const bool water_ok = place.map.has_tag("water_ok"); + const std::vector<std::string> &lines = place.map.map.get_lines(); + + for (rectangle_iterator ri(c, c + place.size - 1); ri; ++ri) + { + const coord_def &ci(*ri); + + if (lines[ci.y - c.y][ci.x - c.x] == ' ') + continue; + + if (_may_overwrite_feature(grd(ci), water_ok, false)) + return (true); + } + + return (false); +} + +static coord_def _find_minivault_place( + const vault_placement &place, + bool check_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; + + // Find a target area which can be safely overwritten. + for (int tries = 0; tries < 600; ++tries) + { + coord_def v1(random_range( margin, GXM - margin - place.size.x ), + random_range( margin, GYM - margin - place.size.y )); + + if (check_place && !map_place_valid(place.map, v1, place.size)) + continue; + + if (_connected_minivault_place(v1, place)) + return (v1); + } + return (coord_def(-1, -1)); +} + static bool apply_vault_grid(map_def &def, vault_placement &place, bool check_place) @@ -255,10 +324,17 @@ static bool apply_vault_grid(map_def &def, // Floating maps can go anywhere, ask the map_def to suggest a place. if (orient == MAP_FLOAT) { + const bool minivault = def.has_tag("minivault"); if (map_bounds(place.pos)) { start = place.pos - size / 2; - fit_region_into_map_bounds(start, size); + fit_region_into_map_bounds(start, size, minivault ? 2 : 0); + } + else if (minivault) + { + start = _find_minivault_place(place, check_place); + if (map_bounds(start)) + fit_region_into_map_bounds(start, size, 2); } else start = def.float_place(); @@ -267,7 +343,7 @@ static bool apply_vault_grid(map_def &def, if (!map_bounds(start)) return (false); - if (check_place && map_place_invalid(def, start, size)) + if (check_place && !_safe_vault_place(def, start, size)) { #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Bad vault place: (%d,%d) dim (%d,%d)", @@ -366,9 +442,9 @@ public: return (sel == TAG || place.is_valid()); } - static map_selector by_place(const level_id &place, bool mini) + static map_selector by_place(const level_id &place) { - return map_selector(map_selector::PLACE, place, "", mini, false); + return map_selector(map_selector::PLACE, place, "", false, false); } static map_selector by_depth(const level_id &place, bool mini) @@ -376,12 +452,12 @@ public: return map_selector(map_selector::DEPTH, place, "", mini, true); } - static map_selector by_tag(const std::string &tag, bool mini, + static map_selector by_tag(const std::string &tag, bool check_depth, const level_id &place = level_id::current()) { return map_selector(map_selector::TAG, place, tag, - mini, check_depth); + false, check_depth); } private: @@ -412,7 +488,6 @@ bool map_selector::accept(const map_def &mapdef) const { case PLACE: return (mapdef.place == place - && mapdef.is_minivault() == mini && !mapdef.has_tag("layout") && map_matches_layout_type(mapdef) && vault_unforbidden(mapdef)); @@ -431,7 +506,7 @@ bool map_selector::accept(const map_def &mapdef) const && (!check_layout || map_matches_layout_type(mapdef)) && vault_unforbidden(mapdef)); case TAG: - return (mapdef.has_tag(tag) && mapdef.is_minivault() == mini + return (mapdef.has_tag(tag) && (!check_depth || !mapdef.has_depth() || mapdef.is_usable_in(place)) && map_matches_layout_type(mapdef) @@ -549,7 +624,7 @@ static const map_def *_random_map_in_list(const map_selector &sel, // a lookup for that tag. if (!chance_tag.empty()) { - map_selector msel = map_selector::by_tag(chance_tag, sel.mini, + map_selector msel = map_selector::by_tag(chance_tag, sel.check_depth, sel.place); msel.ignore_chance = true; @@ -602,10 +677,9 @@ static const map_def *_random_map_by_selector(const map_selector &sel) } // Returns a map for which PLACE: matches the given place. -const map_def *random_map_for_place(const level_id &place, bool want_minivault) +const map_def *random_map_for_place(const level_id &place) { - return _random_map_by_selector( - map_selector::by_place(place, want_minivault)); + return _random_map_by_selector(map_selector::by_place(place)); } const map_def *random_map_in_depth(const level_id &place, bool want_minivault) @@ -615,11 +689,10 @@ const map_def *random_map_in_depth(const level_id &place, bool want_minivault) } const map_def *random_map_for_tag(const std::string &tag, - bool want_minivault, bool check_depth) { return _random_map_by_selector( - map_selector::by_tag(tag, want_minivault, check_depth)); + map_selector::by_tag(tag, check_depth)); } int map_count() @@ -628,11 +701,10 @@ int map_count() } int map_count_for_tag(const std::string &tag, - bool want_minivault, bool check_depth) { return _eligible_maps_for_selector( - map_selector::by_tag(tag, want_minivault, check_depth)).size(); + map_selector::by_tag(tag, check_depth)).size(); } ///////////////////////////////////////////////////////////////////////////// diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h index 0bba9445c9..7068f3eec4 100644 --- a/crawl-ref/source/maps.h +++ b/crawl-ref/source/maps.h @@ -17,8 +17,7 @@ class map_def; -int vault_main(vault_placement &vp, - const map_def *vault, +int vault_main(vault_placement &vp, const map_def *vault, bool check_place = false); // Given a rectangular region, slides it to fit into the map. size must be @@ -28,14 +27,13 @@ void fit_region_into_map_bounds(coord_def &pos, const coord_def &size, const map_def *map_by_index(int index); int map_count(); -int map_count_for_tag(const std::string &tag, bool want_minivault, - bool check_depth = false); +int map_count_for_tag(const std::string &tag, bool check_depth = false); const map_def *find_map_by_name(const std::string &name); -const map_def *random_map_for_place(const level_id &place, bool mini = false); +const map_def *random_map_for_place(const level_id &place); const map_def *random_map_in_depth(const level_id &lid, bool want_minivault = false); -const map_def *random_map_for_tag(const std::string &tag, bool want_minivault, +const map_def *random_map_for_tag(const std::string &tag, bool check_depth = false); void add_parsed_map(const map_def &md); @@ -63,7 +61,7 @@ typedef bool (*map_place_check_t)(const map_def &, const coord_def &c, typedef std::vector<coord_def> point_vector; -extern map_place_check_t map_place_invalid; +extern map_place_check_t map_place_valid; extern point_vector map_anchor_points; const int MAP_CACHE_VERSION = 1009; diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h index d235407577..a29c0c07e7 100644 --- a/crawl-ref/source/stuff.h +++ b/crawl-ref/source/stuff.h @@ -167,6 +167,13 @@ inline bool map_bounds(const coord_def &p) return map_bounds(p.x, p.y); } +// Determines if the coordinate is within bounds of an LOS array. +inline bool show_bounds(const coord_def &p) +{ + return (p.x >= 0 && p.x < ENV_SHOW_DIAMETER + && p.y >= 0 && p.y < ENV_SHOW_DIAMETER); +} + int grid_distance( const coord_def& p1, const coord_def& p2 ); int grid_distance( int x, int y, int x2, int y2 ); int distance( const coord_def& p1, const coord_def& p2 ); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 6ea525759a..a228548ec2 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -3935,7 +3935,7 @@ bool mons_near(const monsters *monster, unsigned short foe) if ( grid_distance(monster->pos(), you.pos()) <= LOS_RADIUS ) { const coord_def diff = grid2show(monster->pos()); - if (env.show(diff)) + if (show_bounds(diff) && env.show(diff)) return (true); } return (false); |