Steps to make sure 'kickedobj' didn't end up as a stale pointer
prevented it from being around to format the reason for death when
a kicking attempt was fatal.
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
Requested by a blind player. The message "Fido moves only reluctantly"
didn't convey enough information to be useful. Describe the reason why
the move is reluctant: "Fido steps reluctantly over <some object>."
If there is a pile, it will describe the top item rather than whichever
cursed item the pet doesn't want to step on.
Change "unlockable" to "broken" so that it won't be misunderstood to
mean "capable of being unlocked". The accompanying suggestion to omit
"broken" unless/until a lock or unlock attempt is made is no good since
the main reason for describing the broken lock is to avoid unnecessary
attempts to lock or unlock a container that the hero knows to be broken
but the player may have forgotten.
I also changed remote look-at for objects to use distant_name(doname)
instead of distant_name(xname) so that qualifiers like "empty" and
"broken" will show up on chests you've investigated before but aren't
standing on now. Monster type for corpse also gets shown, instead of
just 'food (corpse)'. Other remote items will become more verbose,
but only those that the hero has already seen up close.
From a report sent directly to devteam: the #terrain command had the
same bug as the '`' command (which was one of the very first ones
reported): impossible("add_menu called before start_menu"). Only X11
notices.
Reported directly to devteam: teleporting or polymorphing a sink when
dropping the relevant ring into it was suppressed if the hero couldn't
see it happen.
Being unable to see the sink transform or vanish shouldn't stop that
from happening. Since the hero is known to not be levitating (because
of the sink), it can be assumed that he can feel the transformation or
vanishment (is that a real word?), so use the same messages regardless
of blindness.
Prevent commas, equal signs, and tabs in reason for death. Comma
can make while-helpless reason ambiguous in record and basic logfile.
Equal sign can do the same for fixrecord.awk, the awk program that
can be used to fix up corrupted 3.6.0 record files, if it resorts to
constructing logfile records out of xlogfile records. And tab could
break parsing of xlogfile (it should already be excluded though; the
code that lets players assign names to monsters uses mungspaces(), and
one of the things that does is to convert any tab into a space before
squeezing consecutive spaces down to one).
The name alteration shows up for tombstone as well as for file entries.
That could be changed but hardly seems worth the effort. Perhaps the
name sanitizing ought to be moved to the initial naming? At least then
it would be pretty obvious that it was intentional rather by mistake.
Changes to be committed:
modified: doc/fixes36.1
modified: include/extern.h
modified: src/mon.c
Fixes H4148 (bz246) and H4150 (bz248)
comments:
I wielded a c-corpse against a shapeshifting vampire bat (checked with a
stethoscope, it said "shapeshifter".) The bat turned to stone and spawned a
vampire. I hit the vampire and it also turned to stone, so I had two statues
from one monster (vampire bat and vampire.) Not sure if this is a bug or a
feature...
comments:
Engulfed by a fog cloud that was actually a Vampire,
and got the message: "You break out of the vampire!"
Some monsters can't be named, but if the user tried to assign them a
name that matched what they were already called, the rejection message
could be silly. Reported case was "I'm Izchak, not Izchak!". The fix
is more general than just for shopkeepers, although their reject
message was silliest when complaining about the name already in use.
For the cited case, feedback will now be 'He is already called Izchak.'
Duplicate of another recent report as far as drain resistance from
Excalibur/Stormbringer/Staff of Aesculapius not being shown by
enlightenment goes, but this one mentioned that it also wasn't being
shown for lycanthropy. Being inflicted by that does confers level-
drain resistance. were_change() wasn't calling set_uasmon() since
it isn't changing youmonst.data, but set_uasmon() is were intrinsics
conferred by creature form are set up. So call it when changing
were-form. Direct access to u.ulycn wasn't calling it either, so add
a new routine to assign the value to that instead doing so directly.
Mentioned in a completely unrelated report (about energy drain for
vortex attack): the message given if a tame mind flayer is killed by
attempting to eat Medusa's brains had "then is passes" where "then it
passes" was intended.
Reporter thought the fact that two different DREN cases had different
chances to inflict energy drain was an inconsistency, but it was
intentional. Attack for DREN damage has 25% chance to drain energy,
and is never used since no monster has such an attack. Engulf for
DREN damage has 75% chance to drain energy; energy vortices have this,
and the higher chance to be drained while engulfed was intentional.
So add comments explicitly spelling out the 25% and 75% chances.
During beta testing there was a complaint that the energy drain was
much too severe: once hero's current energy drops to 0, excess drain
for current attack and future drains come out of max-energy instead.
That's survivable for caster-type characters with really high energy,
but drained low energy characters to 0 max energy very quickly.
I agreed with the complaint but didn't implement a fix until too late
for 3.6.0. I've since thrown that one out and done this one instead.
Change base drain amount from 4d6 to 2d6, and weaken it more to 1d6
when energy is low or strengthen it to 3d6 when energy is high. It
almost certainly will need further tuning.
Discovered while testing the from-what enhancements to enlightenment.
Polymorphing into a vampire confers the ability to sense humans and
elves without having telepathy or being triggered by blindness. That
would be taken away if you polymorphed into something else, but was
being left in effect if polymorph just timed out and hero returned to
normal form.
Same thing occurred for sensing shriekers if you poly'd into a purple
worm and then reverted to normal (something much less likely to get
noticed and not really subject to abuse if it ever did).
Bonus fix: the code involved was using 0 to mean that Warn_of_mon
from polymorph wasn't in effect, but 0 is also giant ant. This makes
it use NON_PM for that instead.
Enlightenment/attribute disclosure while in wizard mode shows reasons
for some of the intrinsics. This adds some more of those: innately
due to polymorph for lots of things, and innately due to role for
knight's jumping. (Drain_resistance from equipped item came with the
'resistance from Excalibur' patch.)
Enlightenment and end of game disclosure didn't report level-drain
resistance if that was obtained via wielding Excalibur (or Stormbringer
or Staff of Aesculapius). Drain_resistance wasn't one of the attributes
set for intrinsics/extrinsics when wielding or unwielding weapon or
wearing/unwearing other equipment. loseexp() checks resists_drli()
which does check for items in use, so level drain would be aborted,
possibly after messages claimed that it was taming place. I didn't try
to untangle any of that, just changed set_artifact_intrinsic to include
a test for DRAIN_RES.
Reported directly to devteam (12 Dec), user had a config file originally
from MSDOS or Windows and used it on a linux system. That works as-is
except when it contained an invalid option line. Feedback was
"ad option line: "whatever-the-line-was
because of the carriage return character staying in the option buffer
after linefeed was stripped off from CR+LF line end.
He included a patch which replaced this existing fixup after fgets()
if ((p = index(buf, '\n')) != 0) *p = '\0';
with a loop over the whole string changing either '\n' or '\r' to '\0'.
This uses
if ((p = index(buf, '\n')) != 0) {
if (p > buf && *(p - 1) == '\r') --p;
*p = '\0';
}
instead. Ordinarily I would have just cloned the original line and then
substituted \r for \n in the copy, but the report mentioned "I couldn't
get index to work with carriage return". I don't know what he tried to
do or why simple index(buf,'\r') might not work as intended on his
platform, so I went with something that will work even if index()
behaves as strangely as the report suggested.
(We already have a couple of index(string,'\r') calls in use, but I'm
not going to change those unless someone complains about a problem.)
Some people try to set boolean options in the config file
by giving the option a parameter, so allow that:
OPTIONS=color:true
Allowed parameters are "true", "yes", "false", and "no".
Negating an option and giving it a parameter is an error.
_M_UNIX (SCO UNIX) and __linux__ (all flavors of linux?) both call
has_colors() for TTY_GRAPHICS+TEXTCOLOR configuration, but neither
declared it. The new declaration is just a guess based on usage.
Explosion caused by an unseen gas spore resulted in messages about
"explosion" instead of "gas spore's explosion", which is intended, but
followed that with a death reason of "killed by a died" which isn't.
Test case: U-shaped corridor, with a known trap in it.
Before this change, travel would try to move straight at
the target, bumping the wall or walking into a dead-end.
After this, travel will go along the corridor and then stop
right before the trap.
Original patch via AceHack by Alex Smith.
The 3.6.0 feature of dipping only a subset when attempting to dip a large
stack of potions into another potion (other than water) was calculating
the size of the subset poorly. Dipping 9 non-magic potions would always
dip the whole stack, but attempting to dip 10 would split the stack and
dip 2..9, so manually splitting off 9 in advance let the player always
get maximum yield. This anomaly didn't extend to dipping magic potions,
where dipping 2 always dipped "all" 2 and attempting to dip 3..N dipped
2..min(N,9) regardless of N. Also, the decision about whether what you
were dipping was magic was based on the potion being dipped even though
most alchemy formulas yield the same outcome when dipping magic potion
into non-magic or vice versa.
Change the splitting calculation to yield 3..min(N,8) for magic and 7..N
for non-magic, with no extra threshold that can produce anomalies in the
result. Also, the determination of magic vs non-magic is based on the
outcome rather than either of the inputs--unless the outcome is random,
in which case it will be treated as magic if either of the input potions
is magic.
Putting gold into a hero-owned container on a shop's floot gave credit
for the amount of the gold but also set the gold object no_charge, so
it could be taken out without taking away the credit. Then put back
in and taken out as many times as the player liked, doubling the gold
each time until the shopkeeper was out of cash.
I think the proper fix would be to avoid giving credit instead of not
marking the gold no_charge, but that would require multiple additional
changes so I took the easy way out.
Most of the changes to pickup.c are reformatting that it escaped prior
to release. The changes to shk.c are cosmetic and not part of the fix.
Avoid "spellbook of novel" after novel becomes discovered. Now it will
just be "novel". Prior to discovery, it might be on the list as "book
called whatever" if the player assigns a type name.
Also, make novel become discovered after reading one instead of only via
object identification. It already shows up as "novel" in inventory, but
changing its definition to designate it as not-interesting-to-discover
feels disrespectful to the tribute.
Requested during beta testing: if hero can't jump, have #jump command
attempt to cast the jumping spell. This is similar to how #unturn and
^T cast spells when used while lacking the innate ability.
Reading a non-cursed scroll of enchant weapon has a side-effect of
uncursing a weapon welded to hand(s). Make it do the same thing for
cursed tin opener, the only non-weapon/non-weptool that welds to hand.
This is a fix for H4101, bz192.
add non-audio (felt) outcome to yelp()
This also add #wizintrinsic command because testing this was a pain
without a simple, straightforward way to go deaf that didn't time-out
before the situation being tested recurred.
If a character dies with 'multi' at a non-zero value, the reason for
helplessness is appended to the cause of death. But that was taking
place in writeentry(), which is used for every score entry while
rewriting 'record' when a new high score is added. So whenever a new
score with helplessness was added, all existing entries got corrupted
by having the newest game's reason for helplessness tacked on.
Append the helplessness reason while formatting the cause of death
instead of when writing out score and logfile entries. xlogfile is
handled a little differently in case the cause of death plus reason
for helplessness is too long so truncated for record and logfile.
Full reason is still put into xlogfile.
Changes to be committed:
modified: doc/fixes36.1
modified: src/ball.c
I looked up the original bug report that led to bug page C343-20
"When dying immediately on entering a level, the map may show you dying on the previous level."
It was received public report U891:
> When one is being punished and goes down a staircase and dies because the
> ball and chain fell on their head, one gets the message about their death
> while the old level is still being displayed. I wasn't sure whether this
> was a bug or not because on one hand it wouldn't make much sense to
> generate a new level if the character is going to die anyway. However,
> that being said it does make a difference if the character is about to go
> down into a level where one cannot leave bones files, ie medusa or the
> first level of the mines (if i remember correctly). So, if your character
> dies from this does the bones file get left on the level you were on
> (which is still displayed at the time of death) or the level you died as
> soon as you got to (but was never displayed)? Thanks!
Pat had remarked in response: "So this is just a display issue; game play works as intended
(for the program; I imagine you weren't planning to get killed."
A debug trace in wizard mode 3.6.1 beta shows that the relevant code path is this:
NetHack.exe!done(int how) Line 908
NetHack.exe!losehp(int n, const char * knam, char k_format) Line 2678
NetHack.exe!drag_down(...) Line 823
NetHack.exe!goto_level(d_level * newlevel, char at_stairs, char falling, char portal) Line 1316
NetHack.exe!next_level(char at_stairs) Line 1157
NetHack.exe!dodown(...) Line 954
NetHack.exe!rhack(char * cmd) Line 3416
NetHack.exe!moveloop(char resuming) Line 464
NetHack.exe!main(int argc, char * * argv) Line 104
This patch clears the display for the situation in drag_down(),
so the old level is not shown.
If player specified all four facets of role: role, race, gender, and
alignment, via command line or option settings, the tty interface still
asked the player to confirm whether the character's role/&c was ok?
Skip that confirmation when all four things have already been chosen.
The menu for picking an item to name when using the "on discoveries list"
choice for #name or C when that list spanned multiple pages was exiting
for <space> instead of advancing to next page. Space was being assigned
as the selection letter for class header lines, which made no sense.