summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-25 23:36:07 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-25 23:36:07 +0000
commit83b1c7b2cc01d46d8f904b102681e85c044710a0 (patch)
tree9d76a04ce3d820458e18b87c7283f4f68b4f2fa4
parent527fdaf6347eeec4683c418593c1977ab77c5007 (diff)
downloadcrawl-ref-83b1c7b2cc01d46d8f904b102681e85c044710a0.tar.gz
crawl-ref-83b1c7b2cc01d46d8f904b102681e85c044710a0.zip
Place external loot chamber for ziggurat levels with jellies.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7625 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/clua.cc50
-rw-r--r--crawl-ref/source/clua.h8
-rw-r--r--crawl-ref/source/dat/clua/dungeon.lua12
-rw-r--r--crawl-ref/source/dat/clua/point.lua20
-rw-r--r--crawl-ref/source/dat/clua/ziggurat.lua129
-rw-r--r--crawl-ref/source/dat/ziggurat.des12
-rw-r--r--crawl-ref/source/luadgn.cc117
-rw-r--r--crawl-ref/source/mapdef.cc53
-rw-r--r--crawl-ref/source/mapdef.h3
-rw-r--r--crawl-ref/source/mapmark.cc15
-rw-r--r--crawl-ref/source/mapmark.h1
-rw-r--r--crawl-ref/source/maps.cc15
-rw-r--r--crawl-ref/source/maps.h8
-rw-r--r--crawl-ref/source/mon-util.h4
-rw-r--r--crawl-ref/source/monstuff.cc5
15 files changed, 417 insertions, 35 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 2204d17cf1..3be3f4398e 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -658,6 +658,7 @@ void CLua::init_lua()
CLua &CLua::get_vm(lua_State *ls)
{
+ lua_stack_cleaner clean(ls);
_getregistry(ls, "__clua");
CLua *vm = util_get_userdata<CLua>(ls, -1);
if (!vm)
@@ -2516,6 +2517,27 @@ MDEF(hd)
PLUARET(number, mons->hit_dice);
}
+static const char *_monuse_names[] =
+{
+ "nothing", "eats_items", "open_doors", "starting_equipment",
+ "weapons_armour", "magic_items"
+};
+
+static const char *_monuse_to_str(mon_itemuse_type ityp)
+{
+ ASSERT(ARRAYSZ(_monuse_names) == NUM_MONUSE);
+ return _monuse_names[ityp];
+}
+
+MDEF(muse)
+{
+ if (const monsterentry *me = mons->find_monsterentry())
+ {
+ PLUARET(string, _monuse_to_str(me->gmon_use));
+ }
+ return (0);
+}
+
static int l_mons_do_dismiss(lua_State *ls)
{
// dismiss is only callable from dlua, not from managed VMs (i.e.
@@ -2551,6 +2573,7 @@ static MonsAccessor mons_attrs[] =
{ "x" , l_mons_x },
{ "y" , l_mons_y },
{ "hd" , l_mons_hd },
+ { "muse", l_mons_muse },
{ "dismiss", l_mons_dismiss },
{ "experience", l_mons_experience },
};
@@ -2627,6 +2650,12 @@ void clua_push_map(lua_State *ls, map_def *map)
*mapref = map;
}
+void clua_push_coord(lua_State *ls, const coord_def &c)
+{
+ lua_pushnumber(ls, c.x);
+ lua_pushnumber(ls, c.y);
+}
+
void clua_push_dgn_event(lua_State *ls, const dgn_event *devent)
{
const dgn_event **de =
@@ -3051,7 +3080,7 @@ lua_shutdown_listener::~lua_shutdown_listener()
}
lua_datum::lua_datum(CLua &_lua, int stackpos, bool pop)
- : need_cleanup(true), lua(_lua)
+ : lua(_lua), need_cleanup(true)
{
// Store the datum in the registry indexed by "this".
lua_pushvalue(lua, stackpos);
@@ -3067,13 +3096,28 @@ lua_datum::lua_datum(CLua &_lua, int stackpos, bool pop)
}
lua_datum::lua_datum(const lua_datum &o)
- : need_cleanup(true), lua(o.lua)
+ : lua(o.lua), need_cleanup(true)
+{
+ set_from(o);
+}
+
+void lua_datum::set_from(const lua_datum &o)
{
lua_pushlightuserdata(lua, this);
o.push();
lua_settable(lua, LUA_REGISTRYINDEX);
-
lua.add_shutdown_listener(this);
+ need_cleanup = true;
+}
+
+const lua_datum &lua_datum::operator = (const lua_datum &o)
+{
+ if (this != &o)
+ {
+ cleanup();
+ set_from(o);
+ }
+ return (*this);
}
void lua_datum::push() const
diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h
index 2d255189b2..014939c92a 100644
--- a/crawl-ref/source/clua.h
+++ b/crawl-ref/source/clua.h
@@ -73,6 +73,8 @@ public:
lua_datum(CLua &lua, int stackpos = -1, bool pop = true);
lua_datum(const lua_datum &other);
+ const lua_datum &operator = (const lua_datum &other);
+
void shutdown(CLua &lua);
~lua_datum();
@@ -86,11 +88,14 @@ public:
bool is_string() const;
bool is_udata() const;
+public:
+ CLua &lua;
+
private:
bool need_cleanup;
- CLua &lua;
private:
+ void set_from(const lua_datum &o);
void cleanup();
};
@@ -285,6 +290,7 @@ std::string quote_lua_string(const std::string &s);
class map_def;
class dgn_event;
void clua_push_map(lua_State *ls, map_def *map);
+void clua_push_coord(lua_State *ls, const coord_def &c);
void clua_push_dgn_event(lua_State *ls, const dgn_event *devent);
void lua_push_items(lua_State *ls, int link);
diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua
index 4c8d5ddc86..f1997af8e6 100644
--- a/crawl-ref/source/dat/clua/dungeon.lua
+++ b/crawl-ref/source/dat/clua/dungeon.lua
@@ -270,6 +270,18 @@ function dgn.rectangle_forall(tl, br, fpred)
return true
end
+function dgn.gridmark(x, y, grid, marker)
+ dgn.grid(x, y, grid)
+ if marker then
+ local t = type(marker)
+ if t == "function" or t == "table" then
+ dgn.register_lua_marker(x, y, marker)
+ else
+ dgn.register_feature_marker(x, y, marker)
+ end
+ end
+end
+
----------------------------------------------------------------------
-- Convenience functions for vaults.
diff --git a/crawl-ref/source/dat/clua/point.lua b/crawl-ref/source/dat/clua/point.lua
index e57115e033..a6a8077997 100644
--- a/crawl-ref/source/dat/clua/point.lua
+++ b/crawl-ref/source/dat/clua/point.lua
@@ -4,12 +4,32 @@
local point_metatable = { }
+point_metatable.__index = point_metatable
+
function dgn.point(x, y)
local pt = { x = x, y = y }
setmetatable(pt, point_metatable)
return pt
end
+local function sgn(x)
+ if x < 0 then
+ return -1
+ elseif x > 0 then
+ return 1
+ else
+ return 0
+ end
+end
+
+point_metatable.sgn = function (p)
+ return dgn.point(sgn(p.x), sgn(p.y))
+ end
+
+point_metatable.__eq = function (a, b)
+ return a.x == b.x and a.y == b.y
+ end
+
point_metatable.__add = function (a, b)
if type(b) == "number" then
return dgn.point(a.x + b, a.y + b)
diff --git a/crawl-ref/source/dat/clua/ziggurat.lua b/crawl-ref/source/dat/clua/ziggurat.lua
index 0d2b50a818..da27272ad9 100644
--- a/crawl-ref/source/dat/clua/ziggurat.lua
+++ b/crawl-ref/source/dat/clua/ziggurat.lua
@@ -12,6 +12,11 @@
require("clua/lm_toll.lua")
+-- Deepest you can go in a ziggurat - at this point it's beyond
+-- obvious that we're not challenging the player, and one could hope
+-- she has enough loot by now.
+ZIGGURAT_MAX = 81
+
function zig()
if not dgn.persist.ziggurat or not dgn.persist.ziggurat.depth then
dgn.persist.ziggurat = { }
@@ -101,7 +106,10 @@ function ziggurat_level(e)
e.tags("ziggurat")
e.tags("allow_dup")
e.orient("encompass")
- ziggurat_build_level(e)
+
+ if crawl.game_started() then
+ ziggurat_build_level(e)
+ end
end
-----------------------------------------------------------------------------
@@ -114,17 +122,7 @@ function ziggurat_build_level(e)
end
end
-local function zigstair(x, y, stair, marker)
- dgn.grid(x, y, stair)
- if marker then
- local t = type(marker)
- if t == "function" or t == "table" then
- dgn.register_lua_marker(x, y, marker)
- else
- dgn.register_feature_marker(x, y, marker)
- end
- end
-end
+local zigstair = dgn.gridmark
-- Creates a Lua marker table that increments ziggurat depth.
local function zig_go_deeper()
@@ -280,6 +278,9 @@ local function ziggurat_vet_monster(fn)
if mons.experience == 0 or mons.hd > hdmax * 1.3 then
mons.dismiss()
else
+ if mons.muse == "eats_items" then
+ zig().level.jelly_protect = true
+ end
-- Monster is ok!
return mons
end
@@ -329,19 +330,31 @@ local function flip_rectangle(x1, y1, x2, y2)
return { nx1, ny1, nx2, ny2 }
end
-local function ziggurat_create_loot(c)
+local function ziggurat_create_loot_at(c)
local nloot = zig_depth()
local depth = zig_depth()
- local function is_free_space(p)
- return dgn.grid(p.x, p.y) == dgn.fnum("floor") and
- #dgn.items_at(p.x, p.y) == 0
+ local function free_space_threshold(max)
+ local function is_free_space(p)
+ return dgn.grid(p.x, p.y) == dgn.fnum("floor") and
+ #dgn.items_at(p.x, p.y) <= max
+ end
+ return is_free_space
+ end
+
+ local door = dgn.fnum("closed_door")
+
+ local function passable(p)
+ return dgn.is_passable(p.x, p.y) and dgn.grid(p.x, p.y) ~= door
end
local function free_space_do(fn)
- local p = dgn.find_adjacent_point(c, is_free_space)
- if p then
- fn(p)
+ for i = 0, 20 do
+ local p = dgn.find_adjacent_point(c, free_space_threshold(i), passable)
+ if p then
+ fn(p)
+ break
+ end
end
end
@@ -367,6 +380,70 @@ local function ziggurat_create_loot(c)
end
end
+local function ziggurat_create_loot_vault(entry, exit)
+ local inc = (exit - entry):sgn()
+
+ local function find_door_spot(p)
+ while not dgn.is_wall(dgn.grid(p.x, p.y)) do
+ p = p + inc
+ end
+ return p
+ end
+
+ -- Place a door.
+ local doorplace = find_door_spot(exit, inc)
+
+ -- Closed door with the permarock wall feature marker.
+ dgn.gridmark(doorplace.x, doorplace.y, "closed_door", "permarock_wall")
+
+ local connect_point = doorplace + inc
+
+ local map = dgn.map_by_tag("ziggurat_loot_chamber", false)
+
+ local function loot_fallback()
+ crawl.mpr("Failed to create loot vault, giving up", "diagnostic")
+ -- FAIL, generate loot the usual way.
+ ziggurat_create_loot_at(exit)
+ end
+
+ if not map then
+ return loot_fallback()
+ end
+
+ local function place_loot_chamber()
+ return dgn.place_map(map, false, true)
+ end
+
+ local function bad_loot_bounds(map, px, py, xs, ys)
+ local vc = dgn.point(px + math.floor(xs / 2),
+ py + math.floor(ys / 2))
+ local linc = (vc - exit):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)
+ end
+
+ local function connect_loot_chamber()
+ return dgn.with_map_bounds_fn(bad_loot_bounds, place_loot_chamber)
+ end
+
+ local res = dgn.with_map_anchors(connect_point.x, connect_point.y,
+ connect_loot_chamber)
+ if not res then
+ loot_fallback()
+ else
+ ziggurat_create_loot_at(connect_point)
+ end
+end
+
+local function ziggurat_create_loot(entrance, exit)
+ if zig().level.jelly_protect then
+ ziggurat_create_loot_vault(entrance, exit)
+ else
+ ziggurat_create_loot_at(exit)
+ end
+end
+
local function ziggurat_place_pillars(c)
local range = crawl.random_range
local floor = dgn.fnum("floor")
@@ -445,24 +522,28 @@ local function ziggurat_rectangle_builder(e)
local c = dgn.point(x1 + x2, y1 + y2) / 2
- local entry = { x = x1, y = c.y }
- local exit = { x = x2, y = c.y }
+ local entry = dgn.point(x1, c.y)
+ local exit = dgn.point(x2, c.y)
if zig_depth() % 2 == 0 then
entry, exit = exit, entry
end
zigstair(entry.x, entry.y, "stone_arch", "stone_stairs_up_i")
- zigstair(exit.x, exit.y, "stone_stairs_down_i", zig_go_deeper)
+
+ if zig().depth < ZIGGURAT_MAX then
+ zigstair(exit.x, exit.y, "stone_stairs_down_i", zig_go_deeper)
+ end
+
zigstair(exit.x, exit.y + 1, "exit_portal_vault", cleanup_ziggurat())
zigstair(exit.x, exit.y - 1, "exit_portal_vault", cleanup_ziggurat())
ziggurat_place_pillars(c)
- ziggurat_create_loot(exit)
-
ziggurat_create_monsters(exit)
+ ziggurat_create_loot(entry, exit)
+
local function needs_colour(p)
return not dgn.in_vault(p.x, p.y)
and dgn.grid(p.x, p.y) == dgn.fnum("stone_wall")
diff --git a/crawl-ref/source/dat/ziggurat.des b/crawl-ref/source/dat/ziggurat.des
index ed2c9132e0..35e310a2d3 100644
--- a/crawl-ref/source/dat/ziggurat.des
+++ b/crawl-ref/source/dat/ziggurat.des
@@ -45,6 +45,18 @@ lGl
lll
ENDMAP
+
+NAME: ziggurat_loot_1
+TAGS: ziggurat_loot_chamber allow_dup
+ORIENT: float
+MAP
+cccccccccccc
+c..........c
+@..........c
+c..........c
+cccccccccccc
+ENDMAP
+
#######################################################################
NAME: ziggurat1
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 02a74f96be..3fd5b55e86 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -10,6 +10,7 @@
#include <sstream>
#include <algorithm>
+#include <memory>
#include <cmath>
#include "branch.h"
@@ -726,6 +727,18 @@ static int dgn_map(lua_State *ls)
return (0);
}
+ // map(<map>, x, y) = glyph at (x,y), subject to map being
+ // resolved and normalised.
+ if (lua_gettop(ls) == 3 && lua_isnumber(ls, 2) && lua_isnumber(ls, 3))
+ {
+ const int gly = map->map.glyph(luaL_checkint(ls, 2),
+ luaL_checkint(ls, 3));
+ char buf[2] = "";
+ buf[0] = gly;
+ lua_pushstring(ls, buf);
+ return (1);
+ }
+
if (lua_isstring(ls, 2))
{
map->map.add_line(luaL_checkstring(ls, 2));
@@ -940,6 +953,9 @@ static int dgn_grid(lua_State *ls)
PLUARET(number, grd(c));
}
+LUARET1(_dgn_is_wall, boolean,
+ grid_is_wall(static_cast<dungeon_feature_type>(luaL_checkint(ls, 1))))
+
static int dgn_max_bounds(lua_State *ls)
{
lua_pushnumber(ls, GXM);
@@ -2159,6 +2175,103 @@ static int dgn_create_item(lua_State *ls)
return (0);
}
+static std::auto_ptr<lua_datum> _dgn_map_bad_bounds_fn;
+
+static bool _lua_map_place_invalid(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);
+
+ // Push the Lua function onto the stack.
+ _dgn_map_bad_bounds_fn->push();
+
+ lua_State *ls = _dgn_map_bad_bounds_fn->lua;
+
+ // Push map, pos.x, pos.y, size.x, size.y
+ clua_push_map(ls, const_cast<map_def*>(&map));
+ clua_push_coord(ls, c);
+ clua_push_coord(ls, size);
+
+ const int err = lua_pcall(ls, 5, 1, 0);
+
+ // Lua error invalidates place.
+ if (err)
+ {
+ mprf(MSGCH_ERROR, "Lua error: %s", lua_tostring(ls, -1));
+ return (true);
+ }
+
+ return (lua_toboolean(ls, -1));
+}
+
+LUAFN(dgn_with_map_bounds_fn)
+{
+ CLua &vm(CLua::get_vm(ls));
+ 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));
+
+ int err = 0;
+ {
+ unwind_var<map_place_check_t> mpc(map_place_invalid,
+ _lua_map_place_invalid);
+
+ // All set, call our friend, the second function.
+ ASSERT(lua_isfunction(ls, -1));
+
+ // Copy the function since pcall will pop it off.
+ lua_pushvalue(ls, -1);
+
+ // Use pcall to catch the error here, else unwind_var won't
+ // happen when lua_call does its longjmp.
+ err = lua_pcall(ls, 0, 1, 0);
+
+ _dgn_map_bad_bounds_fn.reset(NULL);
+ }
+
+ if (err)
+ lua_error(ls);
+
+ return (1);
+}
+
+// Accepts any number of point coordinates and a function, binds the
+// points as anchors that floating vaults must match and calls the
+// function, returning the return value of the function.
+LUAFN(dgn_with_map_anchors)
+{
+ const int top = lua_gettop(ls);
+ int err = 0;
+ {
+ unwind_var<point_vector> uanchor(map_anchor_points);
+
+ map_anchor_points.clear();
+
+ int i;
+ for (i = 1; i < top; i += 2)
+ {
+ if (lua_isnumber(ls, i) && lua_isnumber(ls, i + 1))
+ map_anchor_points.push_back(
+ coord_def( lua_tointeger(ls, i),
+ lua_tointeger(ls, i + 1) ) );
+ }
+
+ ASSERT(lua_isfunction(ls, -1));
+
+ lua_pushvalue(ls, -1);
+ err = lua_pcall(ls, 0, 1, 0);
+ }
+ if (err)
+ lua_error(ls);
+ return (1);
+}
#define BRANCH(br, pos) \
const char *branch_name = luaL_checkstring(ls, pos); \
@@ -2461,6 +2574,7 @@ static const struct luaL_reg dgn_lib[] =
{ "mapsize", dgn_map_size },
{ "grid", dgn_grid },
+ { "is_wall", _dgn_is_wall },
{ "max_bounds", dgn_max_bounds },
{ "colour_at", dgn_colour_at },
@@ -2524,6 +2638,9 @@ static const struct luaL_reg dgn_lib[] =
{ "create_monster", dgn_create_monster },
{ "create_item", dgn_create_item },
+ { "with_map_bounds_fn", dgn_with_map_bounds_fn },
+ { "with_map_anchors", dgn_with_map_anchors },
+
{ "br_floorcol", dgn_br_floorcol },
{ "br_rockcol", dgn_br_rockcol },
{ "br_has_shops", dgn_br_has_shops },
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 8cbe27c026..57302d789f 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -1663,17 +1663,62 @@ coord_def map_def::float_random_place() const
random_range(minvborder, GYM - minvborder - map.height()));
}
+point_vector map_def::anchor_points() const
+{
+ point_vector points;
+ for (int y = 0, cheight = map.height(); y < cheight; ++y)
+ for (int x = 0, cwidth = map.width(); x < cwidth; ++x)
+ if (map.glyph(x, y) == '@')
+ points.push_back(coord_def(x, y));
+ return (points);
+}
+
+coord_def map_def::float_aligned_place() const
+{
+ const point_vector our_anchors = anchor_points();
+ const coord_def fail(-1, -1);
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "Aligning floating vault with %lu points vs %lu reference points",
+ our_anchors.size(), map_anchor_points.size());
+#endif
+
+ // Mismatch in the number of points we have to align, bail.
+ if (our_anchors.size() != map_anchor_points.size())
+ return (fail);
+
+ // Align first point of both vectors, then check that the others match.
+ const coord_def pos = map_anchor_points[0] - our_anchors[0];
+
+ for (int i = 1, psize = map_anchor_points.size(); i < psize; ++i)
+ if (pos + our_anchors[i] != map_anchor_points[i])
+ return (fail);
+
+ // Looking good, check bounds.
+ if (!map_bounds(pos) || !map_bounds(pos + size() - 1))
+ return (fail);
+
+ // Go us!
+ return (pos);
+}
+
coord_def map_def::float_place()
{
ASSERT(orient == MAP_FLOAT);
coord_def pos(-1, -1);
- if (coinflip())
- pos = float_dock();
+ if (!map_anchor_points.empty())
+ pos = float_aligned_place();
+ else
+ {
+ if (coinflip())
+ pos = float_dock();
- if (pos.x == -1)
- pos = float_random_place();
+ if (pos.x == -1)
+ pos = float_random_place();
+ }
return (pos);
}
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index fa28e7f999..36238a2ba0 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -715,8 +715,11 @@ public:
coord_def dock_pos(map_section_type) const;
coord_def float_dock();
coord_def float_place();
+ coord_def float_aligned_place() const;
coord_def float_random_place() const;
+ std::vector<coord_def> anchor_points() const;
+
bool is_minivault() const;
bool has_tag(const std::string &tag) const;
bool has_tag_prefix(const std::string &tag) const;
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 62549b737b..1d92b09c14 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -804,3 +804,18 @@ bool marker_vetoes_operation(const char *op)
{
return env.markers.property_at(you.pos(), MAT_ANY, op) == "veto";
}
+
+bool feature_marker_at(const coord_def &pos, dungeon_feature_type feat)
+{
+ std::vector<map_marker*> markers = env.markers.get_markers_at(pos);
+ for (int i = 0, size = markers.size(); i < size; ++i)
+ {
+ map_marker *mark = markers[i];
+ if (mark->get_type() == MAT_FEATURE &&
+ dynamic_cast<map_feature_marker*>(mark)->feat == feat)
+ {
+ return (true);
+ }
+ }
+ return (false);
+}
diff --git a/crawl-ref/source/mapmark.h b/crawl-ref/source/mapmark.h
index 03be790910..a0d9a8edaa 100644
--- a/crawl-ref/source/mapmark.h
+++ b/crawl-ref/source/mapmark.h
@@ -25,6 +25,7 @@ class reader;
class writer;
bool marker_vetoes_operation(const char *op);
+bool feature_marker_at(const coord_def &pos, dungeon_feature_type feat);
class map_marker
{
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 062439163b..1549039ee0 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -30,6 +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 int write_vault(map_def &mdef,
vault_placement &,
bool check_place);
@@ -40,6 +43,13 @@ static int apply_vault_definition(
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;
+
+// If non-empty, any floating vault's @ exit must land on these point.
+point_vector map_anchor_points;
//////////////////////////////////////////////////////////////////////////
// New style vault definitions
@@ -247,7 +257,10 @@ static bool apply_vault_grid(map_def &def,
start = def.float_place();
}
- if (check_place && bad_map_place(def, start, size))
+ if (!map_bounds(start))
+ return (false);
+
+ if (check_place && map_place_invalid(def, start, size))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Bad vault place: (%d,%d) dim (%d,%d)",
diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h
index 9ff81cfbf8..a46f861866 100644
--- a/crawl-ref/source/maps.h
+++ b/crawl-ref/source/maps.h
@@ -55,6 +55,14 @@ extern depth_ranges lc_default_depths;
extern dlua_chunk lc_global_prelude;
extern bool lc_run_global_prelude;
+typedef bool (*map_place_check_t)(const map_def &, const coord_def &c,
+ const coord_def &size);
+
+typedef std::vector<coord_def> point_vector;
+
+extern map_place_check_t map_place_invalid;
+extern point_vector map_anchor_points;
+
const int MAP_CACHE_VERSION = 1009;
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 6ca24ba116..2526ab012c 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -170,7 +170,9 @@ enum mon_itemuse_type
MONUSE_OPEN_DOORS,
MONUSE_STARTING_EQUIPMENT,
MONUSE_WEAPONS_ARMOUR,
- MONUSE_MAGIC_ITEMS
+ MONUSE_MAGIC_ITEMS,
+
+ NUM_MONUSE
};
// now saved in an unsigned long.
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 0340d26be2..e742b8c76f 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -37,6 +37,7 @@
#include "itemprop.h"
#include "Kills.h"
#include "makeitem.h"
+#include "mapmark.h"
#include "message.h"
#include "misc.h"
#include "monplace.h"
@@ -7259,7 +7260,9 @@ static bool _monster_move(monsters *monster)
// Jellies eat doors. Yum!
if ((grd(newpos) == DNGN_CLOSED_DOOR || grd(newpos) == DNGN_OPEN_DOOR)
- && mons_itemuse(monster) == MONUSE_EATS_ITEMS)
+ && mons_itemuse(monster) == MONUSE_EATS_ITEMS
+ // Doors with permarock marker cannot be eaten.
+ && !feature_marker_at(newpos, DNGN_PERMAROCK_WALL))
{
grd(newpos) = DNGN_FLOOR;