summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/maps.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-03 10:47:44 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-03 10:47:44 +0000
commitfb869dee39e5953d9240ac1344d029c3ff62d624 (patch)
treeee2a92547a332d91ff0cfafb6e7927868cf5b84c /crawl-ref/source/maps.cc
parentdf23c385f390c4a7beb7c24826085c35e6145b95 (diff)
downloadcrawl-ref-fb869dee39e5953d9240ac1344d029c3ff62d624.tar.gz
crawl-ref-fb869dee39e5953d9240ac1344d029c3ff62d624.zip
[2468791] Reduce distinction between minivaults and floating vaults. All vaults are now handled by _build_vaults.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8169 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/maps.cc')
-rw-r--r--crawl-ref/source/maps.cc200
1 files changed, 136 insertions, 64 deletions
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();
}
/////////////////////////////////////////////////////////////////////////////