Remove the assumption of property index values from the list of
property names. Move the properties that can't have timed values
in normal play to after those which can. (Mainly only matters for
the #wizintrinsic command.)
Bug fix: #wizintrinsic variable 'any' wasn't initialized properly
if 'a_int' is smaller than a long or a pointer. The separator line
I've added was ending up as a menu choice.
Extend the wizard mode #timeout command: show timeouts for all 67
intrinsics rather than just a handful. Most won't appear because
they don't have any way to receive a timed value. Except for...
Extend the wizard mode #wizintrinsic command: allow setting a
brief (30 turn) timeout for any/every intrinsic, not just for
deafness. It ought to prompt for duration, but that's more effort
than I'm willing to expend. This might turn up lots of quirks that
the code isn't prepared to handle (like setting life-saving to
non-zero will break the assumption that it comes from worn amulet).
Perhaps some will warrant fixing, others just a shrug.
There are still some timed events that aren't listed by #timeout:
remaining duration to stay polymorphed in current form, number of
turns until it's safe to pray, luck decay, number of turns until
next attribute exercise/abuse check, probably others that I'm
overlooking.
Bug fix: while testing, I observed
Your limbs have turned to stone.
You have turned to stone.
You can hear again.
You are a statue.
when deafness and petrification were timing out at the same time.
This modifies the stoning and sliming countdowns to extend deafness
duration a little if it's about to time out at the tail end of the
stoning or sliming sequence, so that "you can hear again" won't
happen until after life-saving. There are probably other variations
of simultaneous or near simultaneous timeout that interact oddly.
The different menustyle settings have been offering different degrees
of support for BUCX filtering:
Full : multi-drop, container-in, container-out
Trad, Combo: multi-drop
Partial : none (to be expected; it explicitly jumps past class
filtering, where BUCX gets handled, to a menu of all objects)
This adds pickup, container-in, container-out, multi-unwear/unwield,
and object-ID for Trad and Combo, and multi-unwear/unwield for Full.
(Full behaves like Partial for pickup--not sure why--and for object-ID,
bypassing filters to go straight to a menu of all applicable items.)
There are probably several new bugs--this stuff is very convoluted....
Report #5426 was classified as not-a-bug, but the underlying issue
can be improved.
For item selection where BUCX (bless/curse state) filtering is
supported (mostly for menustyle:Full, but there are a few actions
where Traditional and Combination handle BUCX too), 3.4.3 took the
union of object class and bless/curse state (so ?!B gave all scrolls
and all potions and every blessed item from other classes) but 3.6.0
changed that to the intersection (so ?!B gives blessed scrolls and
blessed potions, period). Since gold is inherently not blessed or
cursed it has been getting excluded during intersection handling
when that includes BUCX filtering. Report #5426 was from a player
who was used to choosing $X when putting newly acquired loot into a
container asking to have the old behavior reinstated.
The ideal fix would be to support both union ($ | X) and intersection
(?! & B), but implementation would be bug prone and the interface,
especially when done for menus, would be cumbersome. Instead, this
adds new boolean option, goldX, to allow the player to decide whether
gold is classified as uncursed--even though it is never described as
such--or unknown. The new-loot-into-container issued can be solved
either via $abcX, where abc lists all classes that have any X items
(when gold is included as one of the classes, its BUCX state is now
ignored for the current selection), or by setting the goldX option
and then just picking X for the types of items to put into the
container (or drop or whatever other action supports BUCX filtering).
The situations where menustyle:Full allows BUCX filtering during
object class specification and styles Traditional and Combination
don't should to be fixed (by extending BUCX support to Traditional
and Combination rather than removing it from Full, obviously).
A small amount of comment formatting in flag.h, plus rearranging
some of the boolean fields into alphabetical order. I only touched
one section of struct instance_flags.
I think this finally quashes the "cursed without otmp" issue.
Various ways of destroying wielded weapon used setnotworn() rather
than unwield(), so the previous change to have unwield() clear the
pending W_WEP bit from takeoff.mask wasn't sufficient to prevent
'A' moving on from another item (blindfold--it's the only thing
processed before primary weapon) to weapon which wasn't there any
more. Also, if weapon was already set in takeoff.what to be
processed on the next move, clearing W_WEP from takeoff.mask wasn't
sufficient either.
Move the previous unwield() 'fix' to setworn() and setnotworn() and
extend it to include cancel_don() if the item being replaced or
removed is in progress or scheduled for next. (Most of the time,
remove_worn_item() has already done that before setworn() or
setnotworn() is called.)
This adds new utility routine strNsubst(), a more versatile version
of the existing strsubst(), that can replace the Nth occurrence of
a substring rather than just the first, and replaces all occurrences
if N is 0.
When working on vampire shape-shifting messages a few days ago I
noticed that a constructed pline/sprintf format was vulnerable to
the player giving the vampire a name with '%' in it and included
a fix for that. This fixes two other instances of the same
vulnerability: a monster with reflection triggering a floating
eye's gaze and the hero using a silver weapon against a silver-
hating monster.
I didn't do a lot of experimenting with the failure, just assigned
the name "foo%s" to the floating eye or the weapon. The resulting
feedback for the relevant messages was garbled due to parameters
being substituted in the wrong place. When that caused there to be
too few arguments to satisfy the format, the final message included
"null" for the missing one rather than triggering a crash while
trying to format something arbitrary from the stack.
I don't think these bugs provided sufficient user control to be
vulnerable to stack manipulation that does something naughty.
I found the dynamic format strings by searching for "%%". There
may be others scattered around the code which don't have that as
an indicator....
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.
When writing the known portion of the current level's map into
dumplog, discard any blank rows at the top (there will already be
one blank line separating it from the text that precedes) and keep
at most one blank row at the bottom (sometimes there won't be any).
Report was for
You finish taking off your boots.
You float gently to the altar. [destination was a red herring]
[take some action to run through moveloop() for next turn]
Your movements are slowed slightly because of your load.
Having float_down() do the next encumbrance check instead of
waiting for moveloop() to do so was straightforward. However,
while testing I noticed the reverse situation (not due to the fix
for the above) when putting on levitation boots
Your movements are now unencumbered.
You finish your dressing maneuver.
You start to float in the air!
Having float_up() do the encumbrance check isn't adequate to fix
this, because it takes multiple turns to put on boots but the
properties they confer are enabled immediately, so moveloop() runs
while hero is already levitating even though the game hasn't told
the player about it yet. Fix is a hack to defer the effect of
levitation on encumbrance until the boots are fully worn, which
might lead to strangeness somewhere. It's also boot-specific so
will need to be updated if some other multi-turn armor that confers
levitation ever gets added.
Some discussion in the newsgroup about nearby peaceful monsters becoming
hostile if they observed the hero attacking a peaceful monster made me
look at the code and I spotted a couple of problems. An auto array was
being initialized in an inner block--some pre-ANSI compilers couldn't
handle that. Worse, it was inside a loop and may or may not have
resulted in unnecessary setup each iteration. Make it static. Oddly,
the array had the same name as a function but `gcc -Wshadow' either
didn't notice or didn't care.
A more significant problem was that mon->mpeaceful was being set to 0
without checking whether mon->mtame was set, potentially resulting in
humanoid pets being both tame and hostile at the same time. This change
prevents that but doesn't do anything interesting about pets who observe
attacks against peacefuls. (I also wonder why chaotic peacefuls now get
upset by seeing other peacefuls be attacked; it seems out of character.)
There was also a check for non-humanoid peacefuls seeing another of the
same species be attacked, but it was checking for an exact match without
regard for littler or bigger incarnations of the same species. I've
added the latter.
This also reformats a couple of block comments.
I couldn't reproduce the reported problem of the "In what direction?"
being issued after the screen was cleared, but bypassing pline() in
favor of putstr(WIN_MESSAGE) for tty prompts did also bypass
if (vision_full_recalc) vision_recalc(0);
if (u.ux) flush_screen(1);
done in pline(). Inadvertent loss of the latter could conceivably be
responsible for the problem. If so, the escape code used by cl_end()
may be broken for somebody's termcap or terminfo setup since clearing
to the end of the line in the message window shouldn't erase the rest
of the screen.
Regardless, the prompting change also bypassed the ability to show
the prompt with raw_printf() if the display wasn't fully intialized
yet, so some change to the revised prompting was necessary anyway.
Switching back from putstr(WIN_MESSAGE) to pline() resulted in
duplicated entries in DUMPLOG message history, one with bare prompt
followed by another with response appended, so more tweaking was
needed. The result is use of new custompline() instead of normal
pline(). custompline() accepts some message handling flags to give
more control over pline()'s behavior. It's a more general variation
of Norep() but its caller needs to specify an extra argument.
Update DUMPLOG's message history to include player responses to
most queries. For tty, both getlin() and yn_function(). For other
interfaces, only yn_function() is covered. (It's intercepted by a
core routine that can take care of the logging; getlin() isn't.)
Also includes saved messages from previous session(s), for the
interfaces which support that (tty), to fill out the logging when
a game ends shortly after a save/restore cycle.
The tty interface was using pline() to display prompt strings.
Having 'MSGTYPE=hide "#"' or 'MSGTYPE=hide "yn"' in .nethackrc
would suppress many prompt strings (in the two examples mentioned,
entering extended commands or the vast majority of yes/no questions,
respectively) and generally lead to substantial confusion even if
done intentionally, so switch to putstr(WIN_MESSAGE) instead.
Separate the message logging out of pline so that other things (for
instance, one-line summary for quest block messages) can be logged.
The code that utilizes this isn't ready for prime time yet.
For FREE_ALL_MEMORY, release DUMPLOG message history when saving.
(Actually, this frees it unconditionally rather just doing so for
FREE_ALL_MEMORY.) It was being freed when logged at end of game,
but not during save. If dumplog message history and interface
message history get integrated, the existing message history
save/restore handling should become applicable instead.
Bug report was:
> "Completed sokoban" achievement was logged when picking up
> a randomly generated bag of holding in the gnomish mines.
The picking-up code was missing checks for the branches, so
you could get the achievements outside the correct branches.
Apparently some screen readers keep reading the status lines
at the bottom of the screen when parts of those change.
Add an option to prevent updates to those lines.
setmangry() and wakeup() were being used for multiple purposes. Add an
extra parameter to track which. This fixes several minor bugs (e.g.
whether monsters with no eyes were angered by (useless) gaze attacks
against them previously depended on the state of a UI option, and
the Minetown guards would be annoyed if you used a cursed scroll of
tame monster on a shopkeeper). It's also a prerequisite for the
Elbereth changes I'm working on.
Adds two new configurable keys to the cursor targeting: 'A' (getpos.menu)
and 'a' (getpos.menu.cansee). First one shows a menu of all interesting
glyphs on the map, second one shows only those in sight.
Travel command also now obeys the "request menu" -prefix, showing
the menu with interesting targets in sight, and then traveling there.
Idea via the NetHack accessibility research by Alexei Pepers.
This is a modified version of Jason Dorje Short's key rebinding
patch, and allows also binding special keys, such as the ones
used in getloc and getpos.
One of the ways to play NetHack on nethack.alt.org is via a HTML
terminal in browser. Unfortunately this means several ctrl-key
combinations cannot be entered, because the browser intercepts
those. Similar thing applies to some international keyboard layouts
on Windows. With this patch, the user can just rebind the command
to a key that works best for them.
I've tested this on Linux TTY, X11, and Windows TTY and GUI.
Yet another accessibility feature. When asked for a location
to travel, and autodescribe is on, the location description
has "(no travel path)" appended, if there is no known path
to that location.
farlook was changed (end of December) to use doname instead of xname
to yield more info for items which had already been seen up close,
but it gave away info about ones which hadn't. So doname was changed
(end of April) to use "some" instead of precise quantity (when the
quantity is greater than 1) for the latter, but that doesn't work
well with corpse_xname() when the hero is blind, yielding "a some
<foo> corpses". While testing the first fix attempt, I noticed that
pickup gave "you can only lift some of the some <foo> corpses".
This fix is far from perfect. farlook can still say "some <item>s"
but lookhere and pickup always say "N <item>s". Picking up a stack
while blind will show "N <item>s" in inventory display, but dropping
it while still blind will revert to "some <item>s" for farlook.
drain_item() always assumed player was responsible, so called
costly_alteration() to adjust shop price of disenchanted item.
If it was unpaid and the effect was caused by a disenchanter
attack rather than by the hero, the feedback was nonsensical.
This also lets a disenchanter hit worn rings, amulet, or blindfold
if no armor gets targetted. Amulets, blindfolds, and most rings
have no charge to be drained, but several types of rings do.
Apparently the compiler for OSX 10.11 + Xcode 7.3.1 is defaulting
to C99 (or C11?) because it is enabling a gcc warning that is
included by -Wextra (newer name for obscure -W) for C99 or later.
lev_comp.y:2276:20: warning: shifting a negative signed value is undefined
[-Wshift-negative-value]
(yyval.i) = SP_OBJ_PACK(-1, (yyvsp[(1) - (1)].i));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../include/sp_lev.h:248:33: note: expanded from macro 'SP_OBJ_PACK'
\#define SP_OBJ_PACK(o, c) (((o) << 8) + ((char) (c)))
\ ~~~ ^
SP_MONST_PACK() and SP_OBJ_PACK() are both called with -1, and
SP_MAPCHAR_PACK() is called with either -1 or -2. The revised
macros add 10 when encoding and subtract it when decoding so that
they can handle -1 through -10 without shifting negative values.
There were also several bitwise ANDs that the bulk reformatting
misclassified as casts of hardcoded addresses.
"Your pair of speed boots glow silver for a moment." should be
"Your pair of speed boots glows silver for a moment.". The fix
reverses a post-3.6.0 change to is_plural(). Also, add new
pair_of() to test for object formatted as "pair of Bars". For verb
usage, that's definitely singular, but for pronoun usage, sometimes
plural seems better (although it might actually be incorrect).
I fixed up the formatting of a block comment in obj.h, but it is
still a candidate for tab cleanup.
The #tip command tries to reduce verbosity by formatting drop messages
with just the object name instead of with full sentences, yielding
Objects spill out: obj1, obj2, obj3, ..., objN.
where the trailing comma or period is included with each successive
object. If an intervening message occurs, such "25 zorkmids are
added to your credit", the rest of the objects will no longer be
extending the original sentence and end up looking silly.
Objects spill out: obj1, obj2,--More--
25 zorkmids are added to your credit. obj3, ..., objN.
This fix causes the post-interruption messages to revert to verbose
format.
Objects spill out: obj1, obj2,--More--
25 zorkmids are added to your credit.--More--
obj3 drops to the floor.--More--
...
objN drops to the floor.
The interrupting message still follows the comma of the partial
sentence, but I don't see any sane way to fix that other than to
abandon the terse format altogether, and doing that makes #tip way
too verbose when the container has a lot of items in it. But #tip
inside shops now does that, since there will always be buy/not-
interested feedback interrupting the terse format in that situation.
For other situations, a full sentence message might end up following
a partial sentence list of dropped items.
There was a more significant bug. Dropping a hero-owned container
with gold in it onto shop floor sold the gold to shk, giving hero
credit. Subsequent #tip gave the hero credit for that same gold
when it spilled out. addtobill(obj) relies on obj->ox,oy to
determine whether events are taking place in a shop, and #tip was
relying on placement onto floor to set those, too late for shop
billing. The fix yields suboptimal results: you're given credit
when you drop the container, then during #tip when you spill the
contents, credit for the gold is removed, then new credit for it
is given. That's down to shop insanity, not tipping behavior.
My old monkey patch was a bit more extensive than Pasi's, although
it didn't originally include letting apes be tameable with bananas.
No sense in throwing it away:
1) Make monkeys and apes be omnivores instead of carnivores.
2) Make bananas be preferred food for herbivore/omnivore subset
of Y-class, so excludes carniverous ape, owlbear, and yeti.
[Sasquatch remain omnivorous but aren't tameable with bananas.]
3) While updating befriend_with_food(), make horses be affected
only by food they might eat, not by meat and corpses and tins.
So they'll be somewhat harder to cope with for characters not
strong enough to kill them. [Dogs and cats are unchanged.]
Not included (not even implemented...):
0) Allow archeologists to choose monkey for starting pet.
[The one in "Raiders of the Lost Ark" didn't actually belong
to Indiana Jones but spent a lot of time accompanying him.]
Bananas are quite rare, and none of the simians are very strong,
so this won't be in any way overpowered - just a bit of flavor.
I think this was originally Derek's change from Sporkhack, but
similar ones have been done in the community multiple times
in the past.
Config file handling remembers the name of the last config file
read in order for options processing to use it in messages, but
it was also reused as default config file name if user-supplied
config file name failed access() test. So the SYSCF file became
the default user config file after it was used. The config file
handling was a real mess.
This patch fixes it for Unix but there is a lot of scope for
typos in the changes for other platforms. Testing is needed.
Make the whatdoes ('&' or '?f') command support the 'altmeta' option
for meta-characters generated by two character seqeunce 'ESC char'.
Also, make it be more descriptive when reporting "no such command"
by including the numeric value it operated on when failing to match
any command. That might provide a way for us to get some extra
information when players report problems with odd keystrokes: we ask
them to type such at the "what command?" prompt and then tell us what
numbers come up.
It's been given a help file to deal with assorted idiosyncracies
which can come up when querying what keys do. Unfortunately that
ended up being way more verbose than intended.
Installation of the extra data file has only been done for Unix.
Other platforms will get "can't open file" if they respond with
'&' or '?' to the "what command?" prompt. The command will still
work though, just without the extra text.