From 3738559721d08c98bbf42b5debddee0cac63196b Mon Sep 17 00:00:00 2001 From: haranp Date: Tue, 17 Feb 2009 20:41:45 +0000 Subject: Fix [2604363]: stashes and autoexplore leaked information about mimics. (Incidentally, if you walk into a mimic by accident, the stash won't go away until the next turn. Technically a bug, but a minor one.) git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9118 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/stash.cc | 80 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 20 deletions(-) (limited to 'crawl-ref/source/stash.cc') diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index d9aa7e1a48..f4f7d2e1ff 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -28,6 +28,7 @@ REVISION("$Rev$"); #include "message.h" #include "misc.h" #include "mon-util.h" +#include "monstuff.h" #include "notes.h" #include "overmap.h" #include "place.h" @@ -301,6 +302,30 @@ bool Stash::is_boring_feature(dungeon_feature_type feat) } } +static bool _grid_has_mimic_item(const coord_def& pos) +{ + const monsters *mon = monster_at(pos); + return (mon && mons_is_unknown_mimic(mon)); +} + +static bool _grid_has_perceived_item(const coord_def& pos) +{ + return (igrd(pos) != NON_ITEM || _grid_has_mimic_item(pos)); +} + +static bool _grid_has_perceived_multiple_items(const coord_def& pos) +{ + int count = 0; + + if (_grid_has_mimic_item(pos)) + ++count; + + for (stack_iterator si(pos); si && count < 2; ++si) + ++count; + + return (count > 1); +} + void Stash::update() { coord_def p(x,y); @@ -313,7 +338,6 @@ void Stash::update() if (grid_is_trap(feat)) trap = get_trap_type(p); - int objl = igrd[x][y]; // If this is your position, you know what's on this square if (p == you.pos()) { @@ -321,12 +345,9 @@ void Stash::update() items.clear(); // Now, grab all items on that square and fill our vector - while (objl != NON_ITEM) - { - if (!is_filtered(mitm[objl])) - add_item(mitm[objl]); - objl = mitm[objl].link; - } + for (stack_iterator si(p); si; ++si) + if (!is_filtered(*si)) + add_item(*si); verified = true; } @@ -334,19 +355,31 @@ void Stash::update() // what the player sees on the square is the first item in this vector. else { - if (objl == NON_ITEM) + if (!_grid_has_perceived_item(p)) { items.clear(); verified = true; - return ; + return; } // There's something on this square. Take a squint at it. - const item_def &item = mitm[objl]; + const item_def *pitem; + item_def mimic_item; + if (_grid_has_mimic_item(p)) + { + get_mimic_item(monster_at(p), mimic_item); + pitem = &mimic_item; + } + else + { + pitem = &mitm[igrd(p)]; + } + + const item_def& item = *pitem; tutorial_first_item(item); - if (item.link == NON_ITEM) + if (!_grid_has_perceived_multiple_items(p)) items.clear(); // We knew of nothing on this square, so we'll assume this is the @@ -356,15 +389,18 @@ void Stash::update() { if (!is_filtered(item)) add_item(item); - verified = (item.link == NON_ITEM); - return ; + // Note that we could be lying here, since we can have + // a verified falsehood (if there's a mimic.) + verified = !_grid_has_perceived_multiple_items(p); + return; } // There's more than one item in this pile. As long as the top item is // not filtered, we can check to see if it matches what we think the // top item is. - if (is_filtered(item)) return; + if (is_filtered(item)) + return; const item_def &first = items[0]; // Compare these items @@ -382,9 +418,7 @@ void Stash::update() if (are_items_same(items[i], item)) { // Found it. Swap it to the front of the vector. - item_def temp = items[i]; - items[i] = items[0]; - items[0] = temp; + std::swap(items[i], items[0]); // We don't set verified to true. If this stash was // already unverified, it remains so. @@ -1081,8 +1115,14 @@ level_id LevelStashes::where() const Stash *LevelStashes::find_stash(int x, int y) { - return const_cast( - const_cast(this)->find_stash(x, y) ); + if (x == -1 || y == -1) + { + x = you.pos().x; + y = you.pos().y; + } + const int abspos = (GXM * y) + x; + stashes_t::iterator st = m_stashes.find(abspos); + return (st == m_stashes.end()? NULL : &st->second); } const Stash *LevelStashes::find_stash(int x, int y) const @@ -1486,7 +1526,7 @@ void StashTracker::update_visible_stashes( const dungeon_feature_type grid = grd[cx][cy]; if ((!lev || !lev->update_stash(cx, cy)) && mode == ST_AGGRESSIVE - && (igrd[cx][cy] != NON_ITEM + && (_grid_has_perceived_item(coord_def(cx,cy)) || !Stash::is_boring_feature(grid))) { if (!lev) -- cgit v1.2.3-54-g00ecf