Fix several obscure bugs that can happen when a guard leads someone
out of a vault:
1) non-pit traps created in the temporary corridor would persist inside
solid rock after the corridor was removed (pits dug by the hero were
explicitly removed but several other trap types are possible);
2) lighting the corridor with scroll/wand/spell left the affected spots
flagged as lit after they reverted to rock; tunneling through that
area, either by digging or by teleporting back to the vault and having
another guard appear, unearthed lit corridor there;
3) if you became encased in solid rock because you were in the temporary
corridor when it was removed (which will happen if the guard is killed
while you're in his corridor), you were only told so if you saw part of
it revert to rock; when blind, you simply found yourself unable to move;
4) dragging an iron ball in the temporary corridor could result in part
of that corridor becoming permanent if the guard was killed; in 3.4.3,
it would only occur if the cause of death took away all the guard's
hit points (which happens for most but not all deaths); in development
code after my recent patch, that would be every cause of death.
#4 could also yield "dmonsfree: <N+1> removed doesn't match <N> pending"
warning in 3.4.3 when the fmon list was scanned and a guard at <0,0> with
no hit points was found but hadn't passed through to the end of mondead()
and m_detach(). The previous patch fixed that, I think/hope. Most guard
deaths won't trigger that; grddead() moves the guard to <0,0> but then
removes the temp corridor on its second try, returns true, and mondead()
finishes normally.
Tested on the unix port; I've updated as many other ports as I can figure
out but they're not tested. See window.doc for info on the changed banner
lines. Also adds the ability to override the generic "Unix" port - used now to get
"MacOSX" into the version line instead of "Unix" (so we don't scare people who don't
know what's going on).
From the newsgroup: after killing a vault guard on a level where
every object had been removed or was held by the hero, object detection
gave feedback about finding something but was unable to show anything.
It was finding the dead guard's inventory at <0,0>, a part of the map
which never gets shown. A dying guard is sent to that location instead
of being killed and deleted, because the data for his temporary corridor
to/from the vault is kept in the egd structure attached to him. That's
somewhat obscure but works; dying guards just need to drop inventory
before being transfered there rather than after.
Depending upon how they're killed, it's possible that the umpteen
places in the code that loop over fmon might have been processing them
as if still in play. This sets their mhp to 0 so such loops will ignore
them, and teaches dmonsfree() not to release them. Once the temporary
corridor has been removed, their isgd flag is cleared and they become
ordinary dead monsters and get deleted from the fmon list the next time
it's purged.
This also lets you throw gold to/at the guard when he tells you to
drop it. He already would catch it, but now he won't treat the throw as
an attack. Any gold he carries will eventually disappear when he does,
so dropping it remains a better option for the player.
The ceiling on the Plane of Water is always "water above", not "sky"
when inside air bubbles and "water's surface" when outside. Also, support
throwing things upwards on the planes of air and water and when underwater
instead of silently dropping the missile in such cases.
This is mainly groundwork for a tangential bit of a forthcoming
levitation fix.
It's possible to ask for help on the first wish attempt, even though
the prompt hasn't been adjusted to mention that yet, so the one message
which is composed dynamically needs to have its phrasing tweaked a bit
more if the user happens to do that.
Also, allow help to be requested even when the cmdassist option is
toggled off. Now that option just controls whether the prompt string is
augmented for retry attempts.
Flesh out the wishing help which becomes available if you give an
unrecognized response to the "for what do you wish?" prompt. It was
quite terse and is now very mildly spoily instead.
Wishing for "{gain,restore,sustain} abilities" works since
makesingular() changes it to "* ability", but a post-3.4.3 change to
makesingular() caused "potion(s) of {gain,restore} abilities" and
"ring of sustain abilities" to fail to match the name, then yield a
random potion or ring. If there turn out to be many other similar
situations, makesingular()'s behavior for "foo(s) of bars" may need
to revert. For now, handle "* of * abilities" as a special case.
While testing the need-hands-to-open-tins patch, I tried to polyself
into a halfling and failed. Add it to the monster name lookup routine as
a variant spelling for hobbit.
While testing something, I noticed that I could eat a tin (off the
floor) while polymorphed into a bat. The code to check whether the hero
could open a tin was testing for limbs, so winged critters passed. Now
it requires hands instead of limbs, and also that the current form be big
enough to be capable of wielding something (even though you don't need to
be wielding anything to open a tin).
This means that a hero poly'd into a dog or cat will no longer be
able to serve him-/herself dinner from a tin....
Simplify many of the intrinsics macros from
#define xxx_resistance (Hxxx || Exxx || resists_xxx(&youmonst))
down to
#define xxx_resistance (Hxxx || Exxx)
by setting or clearing an extra bit in Hxxx during polymorph so that the
resists_xxx() check becomes implicit.
Unfornately there were lots of places in the code that treat Hxxx
as a timeout number--primarily for Stunned, Confused, and Hallucination;
Stunned happens to be one of the revised macros--rather than as a bit
mask, so this patch needed a lot more changes than originally antipated.
More dat/options: include "and" in front of the final entry in
the comma separated lists of options and windowing systems. For the
multi-line options list, fill the paragraph better by splitting lines at
individual words within options rather than at whole option strings.
Also, tweak yesterday's check for DEFAULT_WINDOW_SYS being undefined
so that it actually works as intended.
Show the 'v' output (full version number plus build date-time) as
the first line of '#version' output (build time configuration settings).
It isn't simple to do that when generating dat/options (there's some
port-specific tweaking going), so do it at run-time by processing that
file one line at a time instead of passing it through a pager routine.
This also inserts an "About NetHack" entry as the first choice in
the menu for '?', the way that most Windows programs have interactive
help organized. Picking that gives the same output as using #version.
'make depend' manually updated for Unix and VMS (add dlb.h to version.*).
Change the windowing system section of generated file dat/options
to omit "with a default of <foo>" when it has listed just one enabled
windowing system.
This also adds checks to make sure DEFAULT_WINDOW_SYS is defined,
at least one xxx_GRAPHICS option is enabled, and that the default matches
[one of] the enabled xxx_GRAPHICS.
Move the toptenwin option from flags to iflags to keep it out of
save files, thus preventing odd behavior from win32 (nethackW.exe) when
restoring and finishing games started and saved with tty (nethack.exe).
[See cvs log entry for flag.h for more complete explanation.]
Using the two Windows binaries, starting a game with the tty
interface (nethack.exe) and saving, then restoring and finishing with
the win32 interface (nethackW.exe) would display the topten output as a
series of popup windows displaying one line at a time. The win32 binary
forces the toptenwin option to 1, but when restoring a saved game that
would get overridden by data from the save file and could end up 0.
This change keeps the toptenwin option out of save files, like color
and other display-oriented features that might not be applicable when
restoring on something with different capabilities. Separate binaries
for alternate interfaces aren't quite the same situation, but close enough.
The toptenwin option can still be toggled interactively with 'O', but the
new value will disappear if you save rather than finish. Setting it once
via config file or environment variable is the preferred way to go if you
want to override the default behavior.
Both trunk and branch get iflags.toptenwin added. For the trunk,
flags.toptenwin is simply deleted and patchlevel.h's EDITLEVEL is bumped.
For the branch, flags.toptenwin is renamed and becomes unused, while
EDITLEVEL is left alone. Leaving a dummy field in the old toptenwin slot
of struct flags preserves save file compatability with 3.4.3.
Use the grave accent (back tick) character as the keystroke for a
new command which prompts for an object class and then shows a subset of
the discovered objects list covering just the selected class. Similar
to the 'I' variant of 'i' for viewing inventory, and mainly useful once
the '\' discoveries list has grown long.
<email deleted> suggested that eating a cursed apple
give a Snow White reference. The apple eaten by Snow White is described
as poisoned, but cursed seems close enough. Fall asleep for 20..30 turns
if you eat a cursed apple when you lack sleep resistance.
Revert a change from five weeks ago which added M1_NOHANDS to the
jabberwock definition. The jabberwock illustration from Lewis Carroll's
_Through_the_Looking_Glass_ depicts one with its forelegs held like arms
and the forefeet look like clutching hands. Enormous hands, but
nethack's one-size-fits-all object model means they can manipulate things
just like anybody else's hands.
The preliminary implementation of PANICTRACE on VMS had a "Fixme"
that this fixes, and a "TODO" that this makes moot, but the main reason
for this patch is that vmsmisc.c had been changed to call vms_define(),
which resides in vmsunix.c. Since vmsmisc.obj is linked into progarms
in util/ and vmsunix.obj isn't, enabling PANICTRACE caused linking
problems for those. This moves the code that wants to call vms_define()
into vmsunix.c (despite the fact that it's not even vaguely related to
Unix emulation), so that it only matters to nethack and doesn't impact
the utility programs anymore.
This uses a VMS facility called LIB$INITIALIZE to call code before
main() starts. It's rather messy--at least when written in something
other than assembler or Bliss--and shouldn't be needed for nethack,
but I couldn't figure out how to trap the condition signalled by
lib$signal(SS$_DEBUG) when the debugger isn't available to do so, so I
needed a way to make issuing that signal be conditional upon debugger
availability. One of the arguments passed to LIB$INITIALIZE-invoked
routines contains information that makes if feasible to deduce whether
the debugger is available.
Even when PANICTRACE is disabled, that's useful for handling abort
due to panic while in running in wizard mode.
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.
This might fix the following buglist entry
|Teleporting while using tiles may place you one tile beyond the edge of
|the display screen, and place the crosshair on empty space.
Various bits of code, including teleport, are assigning directly to
u.ux,u.uy instead of calling u_on_newpos(). It wouldn't be an issue for
small tiles where the whole map fits on the screen, but it probably is for
bigger ones where clipping is in operation. Using u_on_newpos() adjusts
the clipped map right away but changing u.ux,u.uy directly won't do so
until control returns to moveloop() and it eventually calls cliparound().
Usually the hero's position only changes by one column and/or row, hence
stays within the clipping margin, but that's not the case for teleport
nor for hurtling (throwing recoil while levitating, &c).
Perhaps all the places that assign u.ux,uy should call u_on_newpos()
instead? Most--all?--of them aren't updating u.usteed->mx,my, but I
guess that monster's coordinates don't matter since it isn't placed on
the map.
Allow wishing for a "potion of detect objects" to generate a
"potion of object detection", or for a "spellbook of monster detection"
to generate a "spellbook of detect monsters".
To get a spellbook you'll need to explicitly specify "spellbook"
even when using a name that's unique to books: asking for "detect food"
will yield a "scroll of food detection" rather than "spellbook of detect
food" because it finds potions and scrolls first. [That's nothing new
for the case where a spellbook and potion or scroll have the same name,
only new behavior for "detect X" vs "X detection" matches.]
Wishing for "detect food" used to yield a random food item rather
than a "spellbook of detect food". That's fixed now, although as
mentioned above it will actually produce a "scroll of food detection".
Fix one of the issues noticed while investigating the report of a
shopkeeper sighing when a hero died without owing anything. If the death
takes place outside of any shop on a level with multiple shopkeepers, the
first one in the fmon list would be the one who had access to the dying
hero's inventory, even if nothing was owed to that one and something was
owed to another shopkeeper. Now the one who is owed gets first chance to
take the hero's possessions.
When dying inside a shop, the keeper of that shop takes control of
the possessions regardless of whether he or anyone else is owed anything.
That hasn't changed, except that if the hero is simutaneoulsy inside
multiple shops (within a wall spot shared by two or more shops) and owes
money to one of them, the one who is owed will take his inventory even if
the other shk is found first.
This doesn't include any changes to feedback given when the hero dies
in the presence of shopkeepers.
From a bug report, if the high scores file
is brand new (empty), statues placed in a cockatrice nest (special room)
end up all being giant ant statues. Statue creation for that room
suppresses object initialization (to prevent the statues from containing
spellbooks), so statue type is left as 0 by mkobj(), then when 'record'
is empty it never gets overridden with a role value as intended.
This forces obj->corpsenm to be initialized as NON_PM instead of 0
by default, then overrides that for corpses, statues, and figurines even
when mkobj()'s caller requests that initialization be suppressed. So if
'record' is empty, there will be a sensible fallback statue type.
obj->corpsenm is overloaded for leashes ('leashmon', mon->m_id),
potions ('fromsink', fountain quaff hack), spellbooks ('spestudied', the
number of times the book has been read), and loadstones (corpsenm hack to
handle singular vs plural for "you can't let go of that/those" message).
If there are any other hidden corpsenm overloads, they may behave
strangely now that corpsenm is defaulting to -1 instead of 0....
Change the way wishing for bear traps in wizard mode is handled so
that spelling of "bear trap" vs "beartrap" doesn't affect the result.
Land mine doesn't have a similar spelling variation, so it already had to
be handled differently (if you wanted an armed trap, you needed to append
something--anything--such that it didn't match the object name). Now
they're consistent with each other. By default, you'll get an object
regardless of whether you include a space inside the name, and you'll
need to specify a prefix ("trapped") or a suffix ("trap"--actually,
anything other than "object") to get an armed trap placed on the ground.
"bear trap", "beartrap", "untrapped bear[ ]trap", "bear[ ]trap object"
will yield the disarmed object,
"trapped bear[ ]trap", "bear[ ]trap trap", "bear[ ]trap<anything else>"
will yield an armed trap.
"land mine" works the same way, treating the embedded space as optional
even though both object and trap include it.
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).
Partial rewrite of escapes(), mostly changing its if-then-else
logic so that end-of-string can be checked once instead for each case.
The previous version had a bug if the input string ended with backslash
and one decimal digit (due to being lumped together with the handling
for trailing \X or \O).
From a bug report, the function escapes(),
which is used during options parsing for various options that accept
string values, is given user-controlled input that could end with a
backslash or caret (or two character "\M"). Such a malformed escape
sequence would make it consume the input's end-of-string character and
then keep processing whatever followed. That meant that it could
generate more data than its output buffer was prepared to hold, making
nethack be vulnerable to stack overflow issues.
His example that was supposed to clobber the stack didn't trigger
any trouble for me, and I didn't bother trying the second one that can
allegedly cause the Win32 binary to run another program. But the bug
itself is clearly real.
While looking at fixing the mfrozen issue for monsters (there's no
way to tell whether it's been caused by sleep or paralysis, necessitating
that some messages be vague or suppressed when actions impact monsters
who can't move), I noticed a drawbridge bug for the hero. It was using
the misleadingly named Sleeping intrinsic incorrectly. When that is
nonzero, the hero is prone to falling asleep at random intervals, not
necessarily asleep right now. I've always intended to rename it to
something that's not misleading, but hadn't ever gotten around to doing
so, until now: change the SLEEPING property to SLEEPY and the Sleeping
intrinsic/attribute to Sleepy.
This may be moot for the drawbridge. I can't remember any hero ever
jumping to safety instead of being crushed by either the bridge or its
portcullis, and I'm sure sleepiness hasn't been a factor. So I haven't
included any fixes entry about misusing Sleeping when it meant u.usleep
(or better yet, unconscious(); or even better, Unaware [a post-3.4.3
pseudo-property that tests both unconscious() and fainted() when checking
whether hero is incapacitated]).
Jabberwocks are flagged as animals hence won't use items, or else
this would have been obvious long ago. They weren't flagged as no-hands,
so a hero in their form could wear gloves and/or wield a weapon (or a
cockatrice corpse, whose ineffectiveness when used with a claw attack
which followed a bite attack led to the discovery of this oversight).
I'm not sure what a jabberwock ultimately looks like, but am pretty sure
that it shouldn't have usable hands, particularly ones which are only
usable by a poly'd hero and not by jabberwock monsters.
From the newsgroup: hero poly'd into various monster forms would be
incapable of turning a target to stone when wielding a cockatrice corpse.
Monster forms with a claw attack as their very first attack (second for
incubus and sucubus, handled as a special case) would have that be
converted into a weapon attack. But some monster forms start with bite
attacks and have their claw attacks later; a hero poly'd into such form
wouldn't use his/her wielded weapon.
This fixes that, but it's actually academic (or about to become so).
The only monster capable of wielding a weapon which would then be ignored
was jabberwock, and I think leaving NOHANDS off the jabberwock definition
is a bug in itself (next patch...).
Fix the second of a couple of minor things I noticed when viewing
that guy's ttyrec about a hidden inventory item which turned out to be
scrolls of scare monster on the used-up items section of his shop bill.
He had a lot of scroll prices which started as $X00 and were changed
to $Y99 due to integer division roundoff when being hit with a 1/3 price
increase for unID'd items followed by 1/2 price increase for low charisma:
100 -> 133 -> 199
200 -> 266 -> 399
Forcing things to round up instead of truncate would help in some cases
but yield $Z01 in others. Rather than doing that, this accumulates the
adjustment factors and then uses them to make one calculation which gives
a better result:
100 -> 200
200 -> 400
Other values and/or other adjustments might not work out so well, but I
don't think they'll ever become prices which look worse than before.
For a single increase of 1/3, 100 still yields 133 but 200 now gives 267
(so ends up differing from the combined price for two 100->133 items).
Fix the first of a couple of minor things I noticed when viewing
that guy's ttyrec about a hidden inventory item which turned out to be
scrolls of scare monster on the used-up items section of his shop bill.
Be more precise when a shopkeeper gives the hero credit for dropped
gold. Instead of just displaying
N zorkmids are added to your credit.
show either
You have established N zorkmids credit.
when you had no previous credit, or
N zorkmids added to your credit; total is now X zorkmids.
when adding to existing credit.
From a bug report, a hero hiding on the
ceiling while poly'd into a piercer or lurker-above could be moved long
distances when a monster attacked his location, because when the attacker
moves into hero's spot, hero's new location is chosen before the attacker
had released its own spot. If things are crowded, the nearest open space
can be quite far away, including beyond nonpassable walls. Fix by taking
attacker off the map before choosing hero's destination, so in crowded
conditions they will likely end up trading places.
This also prevents eels and sharks from moving onto land when the
hero has hidden on the ceiling next to their pool. They'll miss without
moving into hero's spot, but the hero will become unhidden so they'll be
able to make ordinary water-to-shore attack on their next turn.
Lastly, when the attacker is a long worm, the spot chosen for hero
might be filled by its tail by the time hero actually moves. So double
check and possibly re-select target spot after moving a worm's tail.
From a bug report, if you dismount
from a steed whose legs are wounded, you won't recover the point of
dexterity which was removed when they becme injured. He noticed the
case where the steed had just died, but it happens for voluntary
dismount too (actually any dismount except one which wounds the hero's
legs in the process: DISMOUNT_THROWN or DISMOUNT_FELL).
It seems rather odd that the hero temporarily loses Dex when the
steed becomes injured, but I haven't changed that.
From a bug report, you could obtain
a saddle for free if it was dropped (while worn) by a dying pet inside a
shop. That's intentional, but it was happening even when the hero was
not in the shop, which doesn't seem right. Change things to only set it
no_charge if hero is within the same shop (including standing in the
doorway or a temporary wall breach, not just when all the way inside) at
the time of the drop.
I hadn't tried the build script vmsbuild.com in a long time....
vmsbuild.com wasn't compiling src/sys.c;
vmsbuild.com and Makefile.src+Makefile.utl had some linking discrepancies;
Makefile.top, Makefile.dat, Makefile.doc - replace old SCCS id/date/rev
comment with current cvs one (done for .src & .utl a month or so back);
config1.h - running DEC C in VAX C compatability mode to test linking
yielded a diagnostic about signed in the schar typedef for every file.
From a bug report, applying unlit Candelabrum
of Invocation when its candles had 1 turn's worth of burning left would
give a message that the candles were burning but not actually light them
if done anywhere other than the invocation location. Their burn time is
cut it half when not at that spot, and dividing an age of 1 yielded 0,
confusing begin_burn(). They wouldn't light and they couldn't be replaced
since they'd never get used up.
The problem is real, but the chance of it actually happening in
normal play is just about zero. This applies his suggested fix of
rounding the halved burn time up instead of down so that it can't yield 0.
It also applies his suggestion that the Candelabrum treat the invocation
spot like any other location once invocation has produced stairs there,
just as the Bell and the Book do.
When requiring "no" to reject in addition to "yes" to confirm one
of the paranoid_confirmation prompts, only loop a handful of times before
giving up and rejecting (in case there's some hangup-like situation that
isn't hangup enough to switch over to using ESC for further input).
There's no "that's enough tries" feedback; after 6 tries it just stops
asking for a yes or no answer and behaves as if it had gotten no.
A couple of extensions to the paranoid_confirmation option:
1) add paranoid_confirmation:Confirm -- setting this means that any
prompt where the other paranoid_confirm flags have been set to require
a yes response instead of y to confirm also require explicit no rather
than arbitrary non-yes to reject. It will reprompt if you don't answer
"yes" or "no" (unless you use ESC, which is treated the same as "no").
2) add paranoid_confirmation:bones -- control whether the "save bones?"
prompt in wizard mode requires yes instead of just y. The original user-
developed paranoid_confirm patch required yes unconditionally here, and
I left that out thinking it was undesireable. But after testing the
"your body rises from the dead as <undead>..." fix a couple of days ago,
where you now get an extra message and consequent --More-- prompt just
before "save bones?", I've changed my mind about its usefulness, provided
that it's settable rather than unconditional.
Handling paranoid_confirmation:bones outside of wizard mode is a
bit tricky. Right now, it can still be seen via 'O' if it has been set
in NETHACKOPTIONS, but it won't show up in the menu if you use 'O' to
interactively change the value of paranoid_confirmation. I'm not sure
whether that's the right way to go; it might be better to let non-wizard
users uselessly toggle it on and off rather than only partially hide it.
Or maybe it should be hidden from the current value even when it's set.
Or decline to set it in first place, despite external option settings.
I don't think this is useful enough to recommend ordinary users
enable it, but it's close enough to being useful that I don't want
to leave it to become subject to bit rot like umpteen other unfinished
patches. Anyone running in wizard mode who has a panic already gets
pushed into the debugger on VMS, although it doesn't work for what might
be considered the most important configuration (a secure playground, as
opposed to the wide-open one I've always been content to leave mine at).
From a bug report, receiving the
message "Your body rises from the dead as an <undead>..." gives away
the fact that bones are being created (and its absence when applicable
undead kills the hero gives away the fact that bones aren't being
created). Not very interesting for single player installations where
5-10 seconds later the player is going to check the playground for new
files, but matters on multi-user installations where players don't have
access to the directory and sometimes race each other to juicy bones,
such as nethack.alt.org.
At the end of disclosure, give the message whether bones are being
saved or not (for cases where it would have happened when bones are
created). Player won't know whether new bones are becoming available.
Also, prevent risen undead-from-hero from being given random monster
inventory, but explicitly give mummy-from-hero a mummy wrapping if the
hero isn't already carrying one. It will end up being worn; that's
the only armor mummies are allowed to put on.