Noticed while composing a reply to the #H5547 report about named
vampire shape-shift message. The message when a vampire (possibly
in vampire bat form) turned into a fog cloud in order to pass under
a closed door was using a stale cached mon->data value when choosing
the verb. So normal fog cloud or vampire already in fog cloud shape
would "flow" under the door, but newly shifted fog cloud would "ooze"
under the door. I saw this while testing the previous patch but its
significance didn't register at the time.
Report was about "Pet vampire" but the relevant aspect was that the
vampire had been assigned a name, not that it was tame:
You observe a Hilda where a Hilda was.
Investigating this has uncovered two other bugs, one potentially
serious. m_monnam() overrides hallucination but seems to be getting
used to some situations where hallucination should be honored (several
instances). Dynamically constructed format strings are including
monster or object names in the format (rather than the usual use as
arguments), so player assigned names containing percent signs could
cause havoc (a few instances). This fixes some of the former and one
of the latter, but doesn't deal with various other cases revealed by
grep.
If you attack a monster under Elbereth protection, and it wasn't
scuffed by the attack itself, then it'll be automatically removed
with an alignment penalty. It no longer fades from scaring monsters;
only from being abused to attack monsters while protected.
Flying monsters that want to pick up items tend to get stuck above
kelp fronds, particularly on the Medusa level. They're allowed to
move to the water location, but can't reach an underwater item so
end up doing nothing.
While looking at #H4265 ("Bug - Monsters opening doors" about
feedback naming the unseen monster who opened a door), I didn't
find the the problem. But I did notice a couple of suspicious
constructs. Fix an assignment that gave a boolean variable a
value of 16, and add parentheses around 'a & b' in (a & b && c).
The latter isn't incorrect, it just looks strange.
When a chameleon/doppelganger/sandestin took vampire or vampire lord
shape, it stopped taking on new shapes. Vampire shapeshifting was
being applied to all vampires rather than just to is_vampshifter().
When is_vampshifter() is false, the vampire is some other shapeshifter
or Protection_from_shape_changers is in effect, so vampire shifting
doesn't apply.
While testing, I noticed that vampires/lords only turned into bats/
wolves during initial creation. They did turn into fog clouds in
order to pass closed doors but the other alternate forms were ignored.
That's fixed too.
Fix the vault guard error in dochug() discovered by Alex K. The
behavior of a vault guard ignoring Conflict when confronting the
hero in the vault and escorting him through the temporary corridor
isn't affected. 3.4.3 already behaved that way. (I didn't track
the cause of that down so don't know whether it's intentional.)
Bug 271 - #H4167: vampires being fog clouds show up as bats on telepathy
A bug reporter wrote:
> In top level of Vlad's, the vampires hiding as fog clouds in the closets show
> up on telepathy as B, when far-looked as vampire bat. once the door opens they
> are fog clouds.
>
> I currently have telepathy from the PYEC.
The vampire /was/ shapeshifted into a vampire bat, but once the secret door
was revealed, it shifted into a fog cloud in order to pass under the door.
If you were to blast the door with a wand of striking from a distance,
you would have encountered the vampire bat.
This clarifies the situation through better messaging.
--------
Original debug call stack trace:
NetHack.exe!newcham(monst * mtmp, permonst * mdat, char polyspot, char msg) Line 3140
NetHack.exe!vamp_shift(monst * mon, permonst * ptr) Line 1598
NetHack.exe!m_move(monst * mtmp, int after) Line 1219
NetHack.exe!dochug(monst * mtmp) Line 566
NetHack.exe!dochugw(monst * mtmp) Line 100
NetHack.exe!movemon(...) Line 707
NetHack.exe!moveloop(char resuming) Line 105
NetHack.exe!main(int argc, char * * argv) Line 105
Fixing up mis-indented block comments, but hit some files that hadn't
had the earlier mixture of tab replacement, etc, so it's bigger than I
expected. If I get to it, they'll be another round of this tomorrow.
Same sort of stuff as before: some continuation lines with operator
followed by end of line comment (only a few files with those still to
go...), plus tab replaced by spaces in comments, excess parenthesis
removal for return statements, and force function name to be in column
one in function definitions:
type name(args) /* comment */
argtype args;
{
to
/* comment */
type
name(args)
argtype args;
{
I've been spotting those by eye rather than rexexp, so probably missed
some.
Somewhere along the line I started removing redundant parentheses from
return statements, but only in files that needed continuation fixups
so it's not comprehensive.
Allow one item to be taken out of a pile, and leave framework in place
for partial splits so that all monsters will take up to their capacity,
rather than leaving the whole pile if it's too big to take all at once.
Most of the time, rloc() is used for teleporting monsters and it's not a
big deal if they can't find somewhere to go. In a few cases, it is. I
went through all the callsites and made calls to rloc() not cause
impossible()s if they don't need to.
Fixes a bug/suite of bugs reported by ais523.
Reported by the keymasher: "stone at (48,8) is undiggable". Bigroom 4
has a tree at that spot and the whole level is flagged as undiggable.
Undiggable trees were supported on arboreal levels (where their terrain
type is STONE rather than TREE), but not elsewhere. Monster movement
uses IS_ROCK(), which is true for TREEs, but may_dig() uses IS_STWALL(),
which is false for TREEs so doesn't consider the location as being of
interest and fails to disallow digging. But mdig_tunnel() bypasses
may_dig() and tests the NONDIGGABLE bit directly, disallowing digging.
(If this sounds confusing, it's a stroll in the park compared to the
code itself. Apologies for the mixed metaphore.)
Digging away a secret corridor could leave rocks, which doesn't make
a whole lot of sense. Now a monster's dig attempt will reveal the
location as a corridor instead.
This also moves an assignment out of a macro invocation where it was
inviting trouble if that macro gets modified. And reorganizes an 'if'
to put cheaper tests sooner.
I'll push a formatting guide at some point. There may still be
outstanding changes, but please feel free to resolve those as you arrive
a them.
To the best of my knowledge, there is no changes to the actual code
content, but the formatter does have the occasional bug. If you run into
an issue, please fix it!
* derek-elbereth:
ensure that the 'safe' objects remain safe
finish up the changes to trigger erosion on use
initial pass for toning down Elbereth
Conflicts:
dat/castle.des
dat/sokoban.des
include/extern.h
src/engrave.c
src/mklev.c
src/monmove.c
src/zap.c
Any monster with rusting or corrosion attack can eat through
the bars. This includes rust monsters, grey oozes, and black puddings.
Original patch by Malcolm Ryan
There is a lot of code affected by this, and Pat Rankin correctly
observes that it would be better to store roguelike as a level flag
rather than just using Is_rogue_level. A note for the future.
Something I've had in mind for a long time and finally gotten around
to implementing: when you fill in the last pit or hole of a sokoban level,
it's considered to be completed so luck penalties for unsokobanish things
(breaking a boulder, dropping everything and squeezing onto a boulder's
spot, reading a scroll of earth) stop being assessed and most Sokoban-
specific movement restrictions (against pushing boulders diagonally,
squeezing diagonally between boulders, floating over a pit or hole without
falling in, digging of new holes by monsters) are lifted. Teleporting,
level teleporting, and phasing through walls are still prohibited when in
the sokoban branch of the dungeon. (Keeping the non-phasing one in place
prevents taking a shortcut to the final prize in order to bypass the
treasure zoo monsters.)
This adds level.flags.sokoban_rules, defines Sokoban macro to access
it, and replaces most In_sokoban(&u.uz) tests to check it instead. It
gets set when a sokoban level is pre-mapped at the end of level creation,
and if it is set then whenever a trap is deleted, the flag gets cleared
if there are no more pits or holes present on the level.
From a bug report, a
monster incapable of moving could yield the message "<Mon> turns to flee!"
when hit by an attack which scared it. I thought that something to fix
this had already been done, but that wasn't the case. Now it will give
"The immobile <mon> seems to flinch" instead. I'd rather use
mon->data->mmove == 0 ? "immobile <mon>" :
mon->paralyzed ? "paralyzed <mon>" : "sleeping <mon>"
but it presently isn't possible to distinguish between sleep, paralysis,
and being busy doning armor because mon->mfrozen is used for all three.
(I'm not going to worry about the busy case, even though "immobile" sounds
inaccurate for it.)
Also, stethoscope and probing were suppressing "scared" after giving
"can't move", in order to reduce the chance of wrapping the top line.
This changes it to display both status conditions so that scared state
isn't hidden when the target is paralyzed or asleep (or busy).
From a bug report, a stunned monster
moved away from the hero, but remained holding him. That behavior was
still present in the dev code, although the hero was free to move and
would become unstuck as soon as he did so. I don't know how many fixes
for this sort of thing have been made, but they evidently haven't been
made in the proper place. [Perhaps it really ought to be done as a
monster is placed somewhere on the map?]
Get rid of most of the vestiges of the old warning code that was
replaced over 7 years ago. I left the list of colors which were used for
warning flashes.
From a bug report, a monster which
died by moving into a trap which was next to the hero standing on Elbereth
resulted in "The <mon> is killed! The <mon> turns to flee!". An earlier
change made monflee() return if it's given a dead monster, so the fleeing
message is no longer given. This fixes the place where monflee() was
inappropriately being called for a dead monster in the reported situation.
From the newsgroup: Conflict caused tame engulfer to swallow hero.
To try to get out, player hit it (with Magicbane, but that's not relevant
other than to provide an alternate "you hit it" message).
The magic-absorbing blade probes the invisible Audrey!
You get regurgitated!
placing defunct monster onto map?
Program in disorder, &c
[some look_here() feedback]
You kill poor invisible Audrey!
The problem was caused by hmon_hitmon(): it subtracted damage from the
target's hit points, did some bookkeeping and message delivery, then
called killed(). One bit of bookkeeping was to call abuse_pet() and
monflee() when the target is tame, regardless of whether the damage was
fatal. monflee() -> release_hero() -> expels() puts the hero and the
engulfer back onto the map, and that warning was triggered because the
former engulfer had no hit points left.
There's some discussion in the newsgroup about an engraving bug, and
while verifying that it's reproducible I've come across an unintentional
change between the current code and 3.4.3. A recent change made engraving
use accessible(), and that routine wasn't yielding an appropriate value
when applied to a raised drawbridge if the terrain in front of it was ice
or floor (ie, moat or lava had been filled in). Several places which used
the ACCESSIBLE() macro instead of the function suffer from same problem.
This doesn't attempt to address the newsgroup bug (which is that an
engraving written on a lowered bridge transfers to the underlying terrain
if the bridge is raised, even when that terrain is water or lava; the
converse case applies too, an engraving on the ground gets transfered to
the bridge when it lowers).
Turn being unconscious (via several reasons, including fainted from
hunger) into a pseudo-property named `Unaware' and use it in several
places where only being asleep was checked. #H202 was about a stunned
character who got the recovery message when it timed out while fainted.
This suppresses messages for several difficulties when they begin or end
while hero is Unaware. Messages about fatal illness, sliming, or
petrification aren't suppressed; they're too important to hide from the
player. "You feel ..." messages come out as "You dream that you feel ..."
when Unaware; fairly lame but hopefully adequate.
<Someone> reported being swallowed by his pet purple worm during
Conflict, then being stuck inside once Conflict ended. I'm not entirely
sure what dog_move() intended by the "swallowed case handled above" comment.
It returns without letting the pet move when the distance between pet and
hero is 0; that wasn't much in the way of "handling" being swallowed.
Grabbing pets did let go, but peaceful monsters didn't until you actually
attempted to move away from them. Now all four combinations (grabbed or
swallowed by tame or peaceful monster) are handled the same: the monster
will let the hero go next time it gets a chance to try to move, using up
its move in the process.