Blessed scroll of fire allows to choose the explosion location like
scroll of stinking cloud does. This should make it somewhat useful
in the early game.
From the newsgroup, remarking on an usual cause of death seen at NAO.
Surviving a gas spore's explosion (via hit points, not from life-saving)
left "gas spore's explosion" as stale killer.name. Being killed by
opening a drawbridge (but not by closing or breaking one) only assigned
killer.name if it didn't already have a value, so the stale reason got
used: crushed to death by a gas spore's explosion.
This fixes it two ways: clear the stale value after surviving the
explosion, and assign a specific reason when opening the drawbridge.
This also removes stale reason for death set up by various drawbridge
activity. For the usual case, the hero only survives by life-saving
which does its own clearing of killer.name. But there might have been
cases where it was being set for the hero when operating on a monster,
so no life-saving involved. The drawbridge code is not the easiest
code to navigate....
The BONES_POOLS implementation added an extra dot to the bones file
name (only when enabled) which would be a problem on some filesystems.
This changes the name from "bonD0.15.3" to "bon3D0.15" which avoids
the second dot and also fits within 8.3 characters. To enforce that,
the maximum value for BONES_POOLS is now 10 (yielding single-digit pool
numbers 0 through 9).
BONES_POOLS==1 will omit the pool number (that's not a change, just a
reminder), yielding "bonD0.15" and so on. Right now, BONES_POOLS==0
is equivalent to BONES_POOLS=1, but it could be changed someday to
mean that bones files shouldn't be used if we decide to support that.
The pool number as a suffix was being included in content validation,
so it wasn't possible to move "bonD0.15.3" to pool 2 by renaming it to
"bonD0.15.2". I'm not sure whether that was intentional, but it seems
overly draconian. "bon3D0.15" can be renamed to "bon2D0.15" and then
be loaded by a game assigned to pool 2. Also, pre-pool bones can be
retained by renaming to any valid pool and should still work.
The three letter filecode for quest bones has made the bonesid be
broken since 3.3.0 introduced it (the three letter code, not bones-id).
"QArc.2" for level 2 of the Archeologist quest was being written into
the bones file as "rc.2", but worked as intended because validation
when loading bones had the same mistake. This fixes it to use "QArc.2"
when saving and accept either "QArc.2" or "rc.2" when loading, so 3.6.0
bones files (and existing to-be-3.6.1 bones) will continue to work.
Reduce the chance of a player playing on a public server encountering
their own bones, by implementing separate bones pools. The pool a player
belongs to is determined at game start, and only bones in that pool
are used. The sysconf BONES_POOLS allows the sysadmin to define how
many pools there are.
Reported directly to devteam: if applying a grappling hook towards
a target past some water ended up pulling the hero toward the target,
hero would drown without any chance of crawling out of the water.
It used hurtle() to move, and hurtle assumed levitation so didn't
check for entering pools of water except on the Plane of Water.
Previously the "fast-moving" when getting a target location
was always by 8 units. If this option is on, fast-moving
will instead skip the same map glyphs. This should be much more
useful for blind players.
Compound option whatis_filter, filters the eligible map locations
when getting a cursor location for targeting. Accepts 'n' (none),
'v' (map locations in view), or 'a' (map locations in the same area,
eg. room or corridor).
by Excalibur. Noticed on Reddit by Alex, the attempt to fix being
blasted twice by wielded artifact weapon when changing alignment
ended up preventing wielding other role's quest weapons. At the
moment I can't even see how it prevented the double-blast....
This backs out that change and fixes the double-blasting correctly.
When uwep and uswapwep are tested in advance of the rest of invent,
mark them as already processed before entering the loop that checks
all not-yet-processed inventory.
A couple of days ago when verifying the report about being forced to
pay for a second tin when eating one from a stack on a shop's floor,
wishing for 'tins' (rather than 'tins of foo meat') was repeatedly
producing tin wands instead. The name "tin" and the wand description
"tin" in objects[] were being given 50:50 chance for either one by
the 3.6.1 wishing code. Wishing for "tins of spinach" also gave me
a tin wand on the first attempt. Handle 'tin(s)' more explicitly.
This also does some reformatting.
Mark an old 'unconfirmed' bug as 'fixed'. The report was for win32gui
and I can't reproduce the problem or verify that it's gone, but I'm
sure enough about the cause and long-ago fix to put #H4725 to rest....
Report was that the menu for the name-from-discoveries-list command
was reusing a set of punctuation characters for each class of objects.
The key was that '!' was always first, and it is (' ' + 1) so the core
bug of erroneously specifying space for a selector on object class
header/separator lines was being used as the start of the selector
sequence. (Report that led to the fix was that typing space on that
menu always made it finish instead of advance to the next page.)
Reported directly to devteam, eating 1 of 2 tins of spinach from a
shop's floor forced the hero to buy both. (1 was gone, the other was
intact and now owned by the hero rather than the shop. Tins of other
contents behaved similarly.) The bug is easy to fix but not so easy
to explain: eating split one from the stack but passed the remaining
stack to useupf(obj,1) which also split one off and treated that as
used up. The second one was billed as used up and the first one was
added to the bill--as being subjected to a costly modification made by
the hero--and kept intact, now marked no-charge with hero obligated to
pay for it.
Eating 1 of N tins, for N greater than 2, billed for two, one gone and
the other now in a separate stack and marked no-charge. The remaining
N-2 stayed as normal shop goods in their original stack.
The fix is communicate the splitobj() for costly modification up-call
so that the use_up_tin code operates on the one which was split off
the stack rather than on the remainder of the original stack.
I think ^O changed when the dynamic key-binding code was incorporated.
It's a shortcut for #overview in all modes. To get the old wizard mode
behavior, use #wizwhere.
Add an entry for #terrain, expand several of the descriptions, and fix
up the formatting (remove periods in ^ section, align text in # section).
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).
The extra entry about 'A' was intended to go into the "post-3.6.0
code exposed by git repository" section since that's where the
impossible: "cursed without otmp" was introduced.
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....
Noticed while composing a reply to the #H5547 report about named
vampire shape-shift message. The message when a vampire (possibly
in vampire bat form) turned into a fog cloud in order to pass under
a closed door was using a stale cached mon->data value when choosing
the verb. So normal fog cloud or vampire already in fog cloud shape
would "flow" under the door, but newly shifted fog cloud would "ooze"
under the door. I saw this while testing the previous patch but its
significance didn't register at the time.
Report was about "Pet vampire" but the relevant aspect was that the
vampire had been assigned a name, not that it was tame:
You observe a Hilda where a Hilda was.
Investigating this has uncovered two other bugs, one potentially
serious. m_monnam() overrides hallucination but seems to be getting
used to some situations where hallucination should be honored (several
instances). Dynamically constructed format strings are including
monster or object names in the format (rather than the usual use as
arguments), so player assigned names containing percent signs could
cause havoc (a few instances). This fixes some of the former and one
of the latter, but doesn't deal with various other cases revealed by
grep.
> Green dragons should probably not cough in their own breath.
They took no damage, but they did become blind. Make creatures who
breath poison gas (adult green dragons, the Chromatic Dragon) be
immune to gas clouds like non-breathing creatures are.
There's no way to distinguish gas left behind by dragon breath from
that created by scroll of stinking cloud, so gas breathers are no
longer affected by the latter.
Fix a couple of weird messages issued when a shape-shifted vampire
is "killed" and reverts to regular vampire form instead of dying.
First weird one was when vampire has been given a name, as reported.
Second was noticed while fixing that: when cause of death destroys
the creature so thoroughly that there'd be no corpse, the alternate
phrasing for noncorporeal or amorphous form should be used.
old:
The Dracula suddenly transforms and rises as Dracula!
The vampire bat is disintegrated. The seemingly dead vampire bat
suddenly transforms and rises as a vampire!
new:
Dracula suddenly transforms and rises as a vampire!
The vampire bat is disintegrated. The seemingly dead vampire bat
suddenly reconstitutes and rises as a vampire!
Attempting to name the relevant type of item with an artifact's name
(such as a runesword with "Stormbringer") fails with "your hand
slips" in order to prevent turning the item into an aritfact. Since
that only happens when the name is valid, it indicates that the hero
is literate so violate illiterate conduct.
(Naming items in general doesn't affect [il]literacy so that player
can assign names to inventory or stash items to maintain notes.)
This issue has been around for a while but wasn't noticable to players
until some post-3.6.0 tweaking of end of game disclosure. When testing
the DUMPLOG artifact_score fix, I level teleported to the Astral Plane
and performed a cheat ascension. Final disclosure listed high priests
as extinct. Same thing would happen after visiting Moloch's Sanctum
instead. (The latter didn't interfere with creating the Astral high
priests if you got that far, just as creation of the first one there
didn't prevent the other two.)
I forget why high priests are flagged as unique (something I think
I'm responisble for...), but they shouldn't share unique's setting of
extinct during monster creation. (They could be set that way after 4
are created, but this fix doesn't do that. It just treats them like
ordinary monsters so you'd need 127 or 255 or some such to make them
become extinct. Unlike other creatures with a special creation limit,
high priests can be produced when aligned priests gain experience--an
event that I don't recall ever noticing happen.)
I saw dumplog text in a newsgroup posting and the only way I could
recognize what version generated it was that "You entered the dungeon
N turns ago" included the missing-until-recently final period. So,
put nethack's one-line version information as the very first dumplog
text and follow it with the dumped game's start and end date+time.
(That information is useful to know in its own right, but also should
prevent the build date+time shown with the version from confusing
anybody about when the dump was written.)
Along the way, I noticed that the 'counting' phase for artifact_score
was being repeated for '#if DUMPLOG' even though it doesn't generate
output. That had a side-effect of adding points for artifacts twice
(applicable when final score was for an ascension or dungeon escape).
Report was for 'F' followed by '.' reporting "cmdassist: Invalid
direction key!" and then by a direction grid (which happened to
include '.' for self). That behavior applied for all the movement
prefix keys ('m', 'G', &c). When 'cmdassist' was off, "F." would
yield "Unknown command 'F.'." instead.
Now you'll get "You can't fight yourself.", either instead of the
"invalid direction key" part of cmdassist feedback (followed by a
direction grid which excludes up, down, and self since they aren't
applicable for prefix keys) or of the "unknown command" result.
Likewise, "You can't run upward." or "You can't rush downward."
for "G<" and "g>", respectively.
Fix an inconsistency with blindfold removal, eliminating possibility
of a panic (3.6.0) or an impossible (since mid-December, 2016). The
'A' command treated blindfold removal as a multi-turn operation, the
rest of the wear/unwear code as single-turn operation so didn't try
to guard against it being disrupted.
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.
Report was for losing strength when sitting on a throne, but the
message issue was more general than that. Character was wearing
gauntlets of power, so no visible change in strength took place,
but player was told "you're already as weak as you can get" (because
the attempt to reduce strength didn't change current strength;
however, it did change the hero's underlying strength, observable
once the gloves were removed).
There was a beta report last January that was related: in that case
the player thought that gauntlets of power were preventing blessed
potion of gain ability from raising strength, but it was actually
giving a misleading message claiming that strength was already as
high as it could get.
Fix: vary the message when something prevents an attribute change
from being noticeable.
Noticed while working on something else:
You entered the dungeon N turns ago
was missing the terminating period, and when polymorphed into a
1 hit die critter, plural "hit dice" is incorrect. 0 hit dice is
confusing even when fully spelled out, so include an explanatory
remark with it.
Don't include score (available if configured with SCORE_ON_BOTL)
unless player has the 'showscore' option enabled. The value is
an approximation--accurate as far as it goes, but the value can
change depending upon how the game ends. Someone who asks to have
it displayed on the status line will probably be used to that, but
others might start reporting bugs for it.
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.
The automatic annotations supplied for various special levels were
treating the quest leader's summons as being mutually exclusive with
the other things of interest. It's not, so wasn't shown if the entry
portal was on either the bigroom level or the rogue level. Handle it
differently from the rest so that it can stack with annotations for
those levels. (The annotation for the portal itself, which doesn't
get added until traversed, was already handled differently and shown
correctly on those levels.)
Temporary map views for detection or #terrain allow moving the cursor
around to get the brief location description provided by getpos's
autodescribe feature and were doing so by forcing the 'autodescribe'
option to True, then leaving it that way. Save the option value prior
to such operations and restore it after instead of leaving it changed.
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.
Noticed on nethack.alt.org; the Bell of Opening could trigger a
segfault if applied near a trap door or bear trap (and a few others)
that had no monster at the trap location. Reproducible if done
while mounted; {open,close}{fall,hold}ingtrap() would try to access
monst->mx and monst->my of a Null monst pointer if given one when
u.usteed was non-Null.
To-be-3.6.1 bug, caused by a patch (of mine...) incorporated about
a week after 3.6.0 was released that was intended to be for naming
Sting or Orcist. Any artifact creation ended up breaking illiterate
conduct whether user-assigned naming was involved or not (because
oname() is always used to apply the name, not just when do_name() is
executing).
This should be handled differently but I don't want to go through
the dozen and half or so calls to oname() to add an extra argument.
The dumplog data was including a final tombstone unconditionally,
which looked awfully strange for characters who didn't die. Make
it conditional, like actual end-of-game tombstone. (One difference
though: dumplog has a tombstone for hero who died from genocide,
end-of-game does not. I think the latter should display one even
though no grave gets generated.) [Potential for future enhancement:
add some alternate ascii art in place of tombstone for survivors.]
The list of genocided and/or extincted species was never shown
since caller passed 'a' to list_genocided() and it expected 'y'.
Also, once shown, the list entries were lacking indentation that
other sections of the dump generally have.
Both vanquished monsters and genocided/extinct monsters included
a blank line separator even when there was no feedback, making a
noticeable gap in the dumplog text. Have them report "no creatures
vanquished" and "no species genocided", when applicable, so that
their separator lines always have something to separate.
When dumping, omit a couple of blank lines each from vanquished
creatures list, genocided species list, and tombstone so the
relevant sections of the dump are more compact.