From a bug report, the 'D'
command would list 'u' as an item category choice if you were carrying
unpaid items inside a container, but if those were the only unpaid items
then nothing would happen once the dropping stage was reached. Applied
to all menustyles (except partial, which bypasses categories and goes
straight to a menu listing all items). There were two alternatives for
the fix: suppress 'u' as an applicable category when it only applies
to container contents, or include the container among the drop candidates
even though it isn't an unpaid item itself. I went with the latter; it's
simpler to implement and also feels a little more intuitive than behaving
like there aren't any unpaid items present.
When dragon scales or dragon scale mail becomes embedded in poly'd
hero's skin, the '[' command would report "you are not wearing any armor"
but the '*' command showed "a set of <color> dragon scales (embedded in
your skin)". The '[' feedback is more accurate but the '*' feedback is
probably more useful. This changes '[' to be more specific when lack of
worn armor is accompanied by embedded dragon scales/scale mail.
I put the fixes entry in the new features section since the old
behavior wasn't a bug.
Reported recently by <Someone>: probing feedback while engulfed
shouldn't claim that the monster is not carrying anything when the hero
is inside of it. The simple case where it's not carrying anything else
was a trivial one line change; handling inventory plus hero was trickier
and I wouldn't have bothered if I'd realized what it was going to take.
But it's done now; trivial case
The purple worm is not carrying anything besides you.
and harder case
The purple worm's possessions:
Weapons
a - an uncursed dagger
Swallowed Creature
> - human archeologist called wizard
Three years ago <email deleted> reported that
stepping off the end of inventory via typing space to go to the next menu
page wasted his identify scroll. He suggested that some people might do
that because they don't know how to back up in a multi-page menu. I
pointed out the Guidebook section that describes < and ^ to go back one
page or back to start and left things at that. However, traditional mode
reprompts if you step through all of inventory without choosing something,
so this changes identify-via-menu to do likewise. You can dismiss the
menu with ESC to really avoid choosing anything.
This also makes identification of N items when you're carrying N or
fewer unID'd things behave the same as identify all: identify everything
without any prompting.
I suspect--but have no way to test--that there is a subtle difference
in game play between perm_invent and !perm_invent involving object merging
or other activity that depends on whether or not object->dknown is set.
For objects pickup up while blind, where object->dknown is left as is,
the perm_invent config would have such items marked as seen sooner (since
there are umpteen places that call update_inventory() which will end up
setting the seen bit while formatting objects). Non-perm_invent wouldn't
have that done until the user examines invent (or asks to see a list of
objects at the "which object?" prompt for various commands). This patch
effectively examines inventory whenever blindness ends, so both modes get
dknown set as soon as possible. And if we ever add an "effect known" flag
for unseen objects which are used while blind, this would be a suitable
place to perform deferred object discovery.
A bug in some post-3.4.3 code made attempting to remove a worn ring
when wearing two skip inventory the selection and give "you don't have
anything else to remove" if you were wearing gloves and weren't wearing
an amulet or blindfold. The intent was that rings wouldn't be included
as likely candidates in the list of inventory letters to choose from if
you were wearing cursed gloves, but had a copy+paste mistake in the
argument controlling whether to consider the gloves curse state and was
in the wrong section of getobj()'s "ugly hacks". Also, it makes more
sense to require that the player know that those gloves are cursed, so
inaccessibe_equipment() got changed too. [Not knowing that the gloves
are cursed leaves rings listed as candidates; picking a ring will get
removal failure feedback later and mark the gloves as known cursed then.]
Newsgroup discussion about the devnull tournament which started
today has pointed out that ``d4294967296$'' would cause getobj() to create
a gold piece object with quantity 0 which then got dropped to the floor.
(It's specific to gold; other types of objects don't behave that way.)
Also, wrapping which went past negative and zero all the way to positive
again (like 429496729*10+7, yielding 1) wasn't detected.
For GOLDOBJ configuration, relax the 52 object limit for inventory
when gold uses the special $ slot instead of a letter. Takes care of an
old buglist entry from the beta testers. [It will need to be revisited
if we ever implement multiple coin types that can't all fit in one slot.]
Also for GOLDOBJ, prevents nymphs and monkeys from stealing coins,
since allowing that made their steal-item attack be a complete superset
of leprechaun's steal-gold attack.
Reported to us by <email deleted>:
'You are beginning to feel hungry. You trip over it.'
and also recently in the newsgroup by "<Someone>":
There is ice here. *You see here an electric eel corpse.*
Bib hits the electric eel. Bib misses the electric eel.
Bib misses the electric eel. The electric eel misses Bib.
The electric eel misses Bib. *You trip over it.*
slip_or_trip() was oversimplifying things by assuming that if there
is one object at the hero's location, a message about what that object is
has just been given. Any timeout message which precedes Fumbling (lots
of candiates besides hunger) could intervene, as could monster activity
between the hero's move and timeout handling. Aside from the reported
cases, that code hadn't been updated to account for the new pile_limit
option which could be set to 1 and force a popup display instead of the
usual "you see <an item> here". This fix adds a flag that can be used
to track the most recent message. It is cleared by pline for every
message, so pline's caller sets it _after_ the message of interest has
been displayed.
Noticed while looking at something else: doorganize() goes out of
array bounds for alphabet[] when inventory contains something in the '#'
slot, or in the '$' slot for GOLDOBJ config. Both # and $ pass the
(let <= 'Z') test, then produce a negative result for (let - 'A' + 26).
In my case, it was harmlessly clobbering the tail end of buf[] but it
could potentially be a lot worse.
Implement <Someone>'s menu-mode for #name, primarily because it
is the natural place to add [re]naming entries in the discoveries list,
something that was requested in the newsgroup ten or so years ago. The
latter allows changing the type name of something which has previously
been named and is no longer being carried.
This also makes the C command become a synonym for #name or vice
versa; one or the other could now be reassigned to something else.
#name
What do you want to name?
a - a monster
b - a particular object in inventory
c - a type of object in inventory
d - a type of object on discoveries list
Menu group accelerators provide unseen alternate choices: C for monster,
y for individual object, n for object type (and d for discoveries, but
that's only interesting if inventory is empty so that usual b & c are
omitted and discoveries entry moves up to b). These alternates allow
`#name y' and `#name n' to work the same as before, for users who have
trouble retraining their fingers. Using C to name a monster now takes an
extra keystroke, but using `C C' for it could make that be less annoying.
Something that pops up in the newsgroup periodically, with <Someone>
inevitably pointing out the bit of code that the user needs to tweak,
about control of feedback when hero is walking across floor objects.
Implement new option ``pile_limit'' which allows user to set the point
at which the game switches from listing the objects to giving "there are
several/many objects here". Default is 5, same as previous hard-coded
value (1 object gets listed via pline, 2..4 are listed in a corner popup,
5 or more objects yields a pline message instead). Setting pile_limit
to 0 means no limit, so objects will always be listed regardless of pile
size. Setting it to 1 effectively forces no listing since any non-empty
pile size is always at least that big, so can produce "there is an object
here" even though that's no briefer than a pline() to show one object.
From a bug report: moving while blind
and gloveless onto spot containing a cockatrice corpse is fatal if there
are fewer than 5 items there, but harmless when you get the "there are
several/many objects here" result for 5 or more. I thought that this was
something which had already been changed, but it wasn't. Run a touch
check on the whole pile of objects even when no object-by-object feedback
is being given.
Trunk only because it's using the trunk version of corpse_xname().
Simplify the insertion into and removal from of gold in inventory for
the !GOLDOBJ configuration. If GOLDOBJ ever becomes unconditional this
will be superfluous, but in the mean time it unclutters the container and
drop code. Also, tweak a recent getobj() hack so that its purpose might
be a bit clearer.
Reduce the number of questions issued when applying or looting a
container, and offer the opportunity to put things inside before taking
things out. Instead of "Do you want to take something out? [:ynq]",
followed by "Do you want to put something in? [ynq]", this gives just one
prompt; the result is similar to menustyle:full where you start out by
choosing between out, in, and both. There are now two additional choices:
reversed, for both in the opposite order, and stash, to put a single item
inside. Prompt phrasing is rather clumsy; I wanted to keep it short:
"Do what with <the container>? [:oibrsq or ?]", where picking '?' pops
up a brief help window. Inappropriate choices (like 'o'and 'b' when
container is empty) are suppressed from the prompt but still acceptable as
input; " or ?" is suppressed if the cmdassist option has been toggled off,
but entering '?' still works to get help.
Menu mode wouldn't allow 'b' when inventory was empty, despite the
fact that first taking things out might change that. Now 'b' is a viable
choice if the container isn't empty, and the new 'r' is a vialble choice
when inventory isn't empty even if the container is.
Some miscellaneous changes preparatory to enhancing the container
interface. This also fixes a minor inconsistency in object manipulation:
askchain() wouldn't let you split a stack of welded weapons but getobj()
would, so you couldn't get rid of part of the stack using 'D' or #loot,
but you could with 'd' (and post-3.4.3, with #adjust). Now getobj() will
behave like askchain(); if you have 3 cursed daggers welded to your hand,
you won't be able to drop 1 or 2 of them anymore.
There was code to give feedback if you attempted to offer the Amulet
on a regular altar instead of the final high altar, but that code was
unreachable; getobj() yielded "that's a silly thing" whenever you picked
an amulet while not on the Astral (or recently changed, Sanctum) level.
This allows you to try to offer the real or fake Amulet of Yendor on any
altar, but they'll only be listed as likely candidates when on the Astral
level. Conversely, it no longer lists carried corpses as likely candidates
at the Astral high altars; they're still acceptable but not what the hero
is supposed to be fiddling with there. Also, allow corpses on the floor
to be offered on high altars, fixing a complaint we've gotten a few times
over the years. (Unfortunately there's no way to suppress them as likely
candidates on the high altars while still allowing them to be sacrified.)
Several small related changes that ended up being not quite so small:
Allow the Amulet of Yendor to be offered on the altar in the temple
of Moloch's Sanctum level; doing so is fatal. Fake ones can be offered
too, but that doesn't do anything special (they act the same as they do in
the temples on the Astral level). Unlike in the endgame, the Amulet and
its fakes aren't listed as likely candidate for #offer's pick-an-object
prompt; like the endgame, corpses must be carried rather than being on
the altar in order to be sacrificed.
Prevent non-chaotics from destroying the chaotic high altar on the
Astral level via same-race sacrifice. From a bug report. (Chaotics converting non-chaotic high altars
via same method was already handled. I think the behavior for ordinary
altars if wrong here; why should a chaotic altar be destroyed this way?)
Prevent demon princes and demon lords from being summoned in the
endgame. Lesser demons answer instead. Mostly prevents Yeenoghu from
being summoned by a chaotic who performs same-race sacrified on the
chaotic high altar, but might affect the Wizard and arch-liches too.
Identify (via ':', ';', '/') altars in temples on the Astral and
Sanctum levels as "high altars" rather than just as "altars". '/' and ';'
commands now work on those when you're adjacent, like they do when used on
adjacent high priests; from farther away, the altars' alignment is still
suppressed.
From a bug report: you
can dip a worn item such as shirt or suit into a potion of polymorph and
it will become unworn--but as of a couple of days ago, unworn only if the
transformed object's new form can't be worn in the same slot--even if it
is covered by a cursed worn item (suit or cloak). It didn't seem like
trying to fix that special case would be very worthwhile; this fixes the
more general situation of "you could dip worn items even though they were
covered up by other worn items".
In the same report: you could apply grease to rings while wearing
cursed gloves. The code already prevented greasing a suit when it was
covered by a cloak (regardless of whether that cloak was cursed), and a
shirt when it was covered by a suit or cloak or both. This moves that
code into a separate routine which is used for dipping as well as for
applying grease, and now handles rings vs gloves.
Since covered rings, shirt, or suit are no longer eligible to be
dipped or greased, this also makes "?" for the pick-an-item prompt leave
such things out of the list of likely candidates.
[I can't get access to my mail at present, but `cvs update' shows
that there aren't any patch notification messages pending for me.]
Extend a pre-3.4.3 fix--for objects picked up in an untended shop--
to container contents. Without it, dropping a bag or box in a tended shop
and declining to sell it, then picking it back up after the shop has become
untended (shk killed or evicted) would leave the contents with no_charge
set. After that it could be sold in another tended shop, picked back up
for free, then kept or sold a second time. (Picking it back up in the
tended shop would clear the bit; afterwards it behaved normally. And it's
not something prone to abuse; if you can make a tended shop become untended
you really don't need to sell stuff twice. But it'd be noticeably wrong if
anyone ever stumbled across it.)
Inventory display adds "(unpaid, N zorkmids)" to carried unpaid
items, but it didn't show anything comparable for indirect unpaid ones
(hero-owned containers holding shop-owned objects). Now it will include
"(contents, N zorkmids)" in such cases.
Allow '#' as a destination slot if you've given '#' as the source
and there aren't any available inventory letters, making it possible to
use doorganize()'s feature of merging compatible items into one slot even
when that slot is #. ('#' won't work as a destination when the source is
from a regular letter. If the player wants to swap something in letter
slot x with whatever is in the # slot, he'll have to use # -> x rather
than x -> #.)
Also, a post-3.4.3 change made it possible to produce an inventory
that used duplicate letters. Giving a count while specifying the source
slot splits the source object. But the extra '?' choice added to show
inventory letters in use didn't undo the split if player hit ESC to quit
early instead of specifying a destination slot.
Lastly, don't prompt forever if the user doesn't give a valid
destination letter; give up after 5 attempts.
Prevent getobj() from overflowing its inventory letter collection
buffer if someone figures out some new way to fill up their inventory with
a huge number of # entries. Inventory manipulation might become crippled
at that stage but at least it shouldn't be able to trigger a crash.
Also, the !fixinv configuration was never taught about # and did
strange things if you had more than 52 items, both for inventory display
and object selection with getobj.
The reassign()/getobj() situation is definitely confused regarding
gold, using GOLD_SYM in some places and def_oc_syms[COIN_CLASS] in
others, and it's schizophrenic about whether the GOLDOBJ configuration
keeps gold in a letter slot or specially named $ slot. I'm sure there
are some problems there but I'm not planning to try to figure them out.
If someone manages to get three or more items with inventory "letter"
'#', compact inventory selection prompts to list "#-#" instead of showing
every #. It isn't possible to selectively pick a particular one anyway,
so this doesn't affect player choices.
1 #: Which item? [$#a-zA-Z]
2 #: Which item? [$##a-zA-Z]
3 #: Which item? [$#-#a-zA-Z]
4 or more #: same as 3.
This doesn't address the fact that picking up enough boulders as a
giant might overflow the BUFSZ buffer getobj() uses to collect inventory
letters prior to calling compactify() on them.
Change safe_qbuf() so that instead of picking one of three strings
for sprintf() to plug into a prompt string, it actually constructs the
full prompt string itself. Also pass in the unformatted object and a pair
of formatting functions instead of performing dual formatting in advance.
The actual formatting is done via new routine short_oname() which also
takes an object and a pair of formatting routines plus a target length.
It uses the first routine, typically xname() or doname(), and formats the
object, then if the result is too long it makes some transformations, and
tries again. If truncating "called foo" and "named bar" down to 12 chars
and omitting "uncursed, rustproof, thoroughly corroded" attributes still
result in a string that's too long, it uses the other formatting routine.
The latter calls one of several jacket routines around simple_typename()
to produce a short result.
This has been through about four incarnations now and has gotten a
bit less testing each time, but I need to get it in place before I end up
running out of gas and abandoning it. I've got some changes to shk.c
(where safe_qbuf is needed but not currently used) that now need to be
redone and will come eventually.
This is an overhaul to the NetHack drawing mechanism.
- eliminates the need to have separate lists in drawing.c
for the things and their associated explanations by grouping
those thing together on the same inializer in a struct.
- replaces all of these options: IBMgraphics, DECgraphics, MACgraphics,
graphics, monsters, objects, boulder, traps, effects
- drawing.c contains only the set of NetHack standard symbols for
the main game and a set of NetHack standard symbols for the
roguelevel.
- introduces a symbols file that contains named sets of
symbols that can be loaded at run time making it extensible
for situations like multinational code pages like those reported
by <Someone>, without hardcoding additional sets into the game code.
- symbols file uses names for the symbols, so offsets will not break
when new things are introduced into the game, the way the older
config file uchar load routines did.
- symbols file only contains exceptions to the standard NetHack
set, not entire sets so they are much less verbose than all of
the g_FILLER() entries that were previously in drawing.c
- 'symset' and 'roguesymset' config file options for
preselecting a symbol set from the file called 'symbols'
at startup time. The name of the symbols file is not under the
users control, only the symbol set name desired from within the
symbols file is.
- 'symset' config file option loads a desired symbol set for
everything but the rogue level.
- 'roguesymset' config file option loads a desired symbol set
for the rogue level.
- 'SYMBOLS' config file option allows the user to specify replacement
symbols on a per symbol basis. You can specify as many or as few symbols
as you wish. The symbols are identified by a name:value pair, and line
continuation is supported. Multiple symbol assignments can be made on
the same line if each name:value pair is separated by a comma.
For example:
SYMBOLS = S_bars:\xf0, S_tree: \xf1, S_room:\xfa \
S_fountain:\xf4 \
S_boulder:0
- 'symbols' file has the following structure:
start: DECgraphics
Handling: DEC
S_vwall: \xf8 # meta-x, vertical rule
S_hwall: \xf1 # meta-q, horizontal rule
finish
start: IBMgraphics
Handling: IBM
S_vwall: \xb3 # meta-3, vertical rule
S_hwall: \xc4 # meta-D, horizontal rule
finish
- 'symbols' file added to the source tree in the dat directory
- Port Makefiles/scripts will need to be adjusted to move them into
HACKDIR destination
Remove some more code that forced pointers into a long int, and
vice versa where information could be lost (P64 platforms such as
WIN64 have a 64 bit pointer size, but a 32 bit long size.)
This 2nd part deals with timeout functions switching
some arguments from type genericptr_t to 'anything'.
Like part 1, this needs to increment EDITLEVEL in patchlevel.h.
<Someone> reported that he applied an unID'd bag and it became
discovered as a bag of tricks even though a spellbook appeared on the floor
next to him rather than having a monster show up (the monster was a mimic).
Suppress the bag discovery unless you can see or sense a monster appear.
(This doesn't really achieve much for most players, who'll recognize the
bag because they know that only one type of container doesn't prompt to
take things out and/or put things in, but I think it does make sense.)
While mucking with bag of tricks I decided that to be consistent with
the behavior of other containers, the #tip command should release all the
monsters in the bag instead of just one.
And after doing that, I realized that horn of plenty ought to behave
much the same, so #tip will operate on it now. However, it won't be listed
as a likely candidate in the "which item?" prompt unless/until it has been
discovered. (Attempting to empty any other type of horn yields "nothing
happens", same as for a horn of plenty with no charges left.) Emptying a
horn of plenty in a shop can be extremely verbose, but I don't think that
qualifies as a bug and don't currently have any plans to alter it.
When the hero receives the quest artifact "got it" message, set the
artifact's dknown bit in case the hero is blinded. That message describes
the object by name, effectively the same as seeing it up close. (This
would have prevented the "now wearing an Eyes of the Overworld" grammar bug
for monks but not for non-monks, so the previous fix is still necessary.)
This patch by <email deleted> was released
when 3.4.1 was current and has been incorporated into slash'em. It is
extremely useful while using ranged weapons. When both autopickup and
pickup_thrown are enabled, walking across previously thrown objects will
pick them up even if they don't match the current pickup_types list.
[See cvs log for patchlevel.h for longer description.]
It seemed inappropriate to allocate and tack on an oextra
structure just to mark it as unmergable, and the oextra
struct itself wouldn't be released until a save/restore took
place.
This uses one of the freed up oattached bits to prevent the merge.
move oattached and oname and other things that vary
the size of the obj structure into a separate
non-adjacent oextra structure, similar to what has
already been done for mextra. The obj structure
itself becomes a fixed size.
New macros:
#define ONAME(o) ((o)->oextra->oname)
#define OMID(o) ((o)->oextra->omid)
#define OMONST(o) ((o)->oextra->omonst)
#define OLONG(o) ((o)->oextra->olong)
#define OMAILCMD(o) ((o)->oextra->omailcmd)
#define has_oname(o) ((o)->oextra && ONAME(o))
#define has_omid(o) ((o)->oextra && OMID(o))
#define has_omonst(o) ((o)->oextra && OMONST(o))
#define has_olong(o) ((o)->oextra && OLONG(o))
#define has_omailcmd(o) ((o)->oextra && OMAILCMD(o))
changed macros:
has_name(mon) becomes has_mname(mon) to correspond.
The CVS repository was tagged with
NETHACK_PRE_OEXTRA
before commiting these, and
tagged with
NETHACK_POST_OEXTRA
immediately after. The diff
between those two tags is this oextra patch.
The associated mail daemon changes to use an oextra
structure instead of a hidden command located in the
name after the terminating NUL, have not been tried
or tested.
<email deleted> wrote the following on April 10, 2006:
> When blind and levitating, you can produce a message - "You try to feel what
> is lying here on the ice. But you can't reach it!" - which reveals too much
> about the terrain below you.
My recent patch included a typo in a pline() call which broke compile,
and much worse, was accessing scroll of identify after using it up. Cache
scroll->otyp, scroll->blessed, and scroll->cursed instead of re-re-ordering
the identify scroll/spell code.
This patch alters wiz_identify so that it displays an
inventory menu with all items shown identified
without actually identifying them.
You can just press ^I (or whatever the wiz_identify command
is) a second time, while the menu is displayed to actually identify
them (tested with TTY menus only).
Allow rubbing any object against any touchstone even when the latter
is known so only gems make sense. Also, propagate an earlier fix which
allowed rubbing gold against known touchstones to the branch (it had been
trunk only).
cknown and lknown flags for containers are now checked when deciding
whether an item is fully identified, and they're set when identification
takes place. (You'll learn how many items are inside even if you haven't
looked to see what they are yet. This means that an inventory listing of
unpaid items will reveal the contents after you've used enouch magic to ID
an unpaid container.) Also, set those flags for any container in initial
inventory; rogues should know that sack starts out empty.
A post-3.4.3 change dealing with reaching into pits resulted in "you
sit on the air" if you used the #sit command after escaping a pit trap.
Change can_reach_floor() so that caller explicitly controls whether being
on the brink of a pit is a condition that prevents reaching the floor.
This also splits a fairly common message about not being able to reach the
floor into a separate routine.
There is still oddness here: if you're polymorphed into a flyer,
#sit yields "you sit down" followed by "you fly over a pit" (latter occurs
when escaping trap activation). A ceiling hider behaves similarly, but
the second message is "you escape a pit" and doesn't sound quite as silly.
Perhaps #sit should pass TOOKPLUNGE to dotrap(), or maybe there's some
better way to handle this?
When 3.4.0 added the shop price to inventory display of unpaid items,
it resulted in showing that price twice if you used the `I u' command while
carrying just one unpaid object.
k - a potion of object detection (unpaid, 150 zorkmids) 150 zorkmids
With two or more unpaid objects it uses a menu style display and explicitly
suppresses "(unpaid, N zorkmids)" from the inventory formatting. Do the
same suppression when there's one item.
k - a potion of object detection 150 zorkmids