From 83b1c7b2cc01d46d8f904b102681e85c044710a0 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Tue, 25 Nov 2008 23:36:07 +0000 Subject: 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 --- crawl-ref/source/clua.cc | 50 ++++++++++++- crawl-ref/source/clua.h | 8 +- crawl-ref/source/dat/clua/dungeon.lua | 12 +++ crawl-ref/source/dat/clua/point.lua | 20 +++++ crawl-ref/source/dat/clua/ziggurat.lua | 129 +++++++++++++++++++++++++++------ crawl-ref/source/dat/ziggurat.des | 12 +++ crawl-ref/source/luadgn.cc | 117 ++++++++++++++++++++++++++++++ crawl-ref/source/mapdef.cc | 53 +++++++++++++- crawl-ref/source/mapdef.h | 3 + crawl-ref/source/mapmark.cc | 15 ++++ crawl-ref/source/mapmark.h | 1 + crawl-ref/source/maps.cc | 15 +++- crawl-ref/source/maps.h | 8 ++ crawl-ref/source/mon-util.h | 4 +- crawl-ref/source/monstuff.cc | 5 +- 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(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 #include +#include #include #include "branch.h" @@ -726,6 +727,18 @@ static int dgn_map(lua_State *ls) return (0); } + // 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(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 _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)); + 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 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 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 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 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(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 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; -- cgit v1.2.3-54-g00ecf