summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/acr.cc2
-rw-r--r--crawl-ref/source/arena.cc2
-rw-r--r--crawl-ref/source/dat/clua/ziggurat.lua9
-rw-r--r--crawl-ref/source/decks.cc2
-rw-r--r--crawl-ref/source/dungeon.cc253
-rw-r--r--crawl-ref/source/luadgn.cc35
-rw-r--r--crawl-ref/source/mapdef.cc9
-rw-r--r--crawl-ref/source/maps.cc200
-rw-r--r--crawl-ref/source/maps.h12
-rw-r--r--crawl-ref/source/stuff.h7
-rw-r--r--crawl-ref/source/view.cc2
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);