Sanity check failure generated by running the fuzzer, reported
by mkuoppal. The check discovered that the hero's current hit
points were greater than the maximum.
Comments by elunna pointed out where the problem most likely was,
and this attempts to fix the situation, but without a test case
I can't be sure that the fix works.
Both cases being fixed are for formerly fatal incidents (random
chance that poison is fatal, monster touch of death spell) being
'softened' to heavy HP damage (including reduction of maxHP).
The earlier commit I made (045d608) was done without having seen
the relevant comments. It didn't fix anything but did attempt
to make finding the problem(s) easier. It wasn't much help.
Fixes#1252
I don't always want to abort() on an impossible() when debug_fuzzing,
especially if the first impossible() encountered isn't related to the
bug I'm in the midst of trying to hunt down.
I often have breakpoints on impossible() anyway, and I'd like a simple
way to avoid the panic() call during a lengthy debug session.
Make iflags.debug_fuzzer an xint8 instead of a boolean.
Call abort() only if iflags.debug_fuzzer is set to 1.
That allows setting iflags.debug_fuzzer to 2 in order to bypass the
abort call, and make use of other breakpoints that have been set
to narrow down a particular issue.
Issue a livelog/#chronicle message if saving-grace saves the hero.
Right now it's classified as conduct for livelog filtering, because
I didn't want to implement a new category (needs update of global.h
and also the template 'sysconf') and conduct felt like the best fit
of the existing classifications.
Report whether saving-grace is available or already used, among
the attributes of magical enlightenment or end-of-game disclosure.
And move the fixes entry for it from the fixes section to the new
features section of fixes3-7-0.txt.
It seems likely that someone will want to turn not using saving-
grace into a tracked conduct. That seems like overkill to me, not
to mention inflating the N for "N conduct games".
I've been investigating issue #1252 (while the fuzzer was running,
sanity_check complained that hero's current health was greater
than maximum health) off and on for three months and haven't found
the cause.
I've checked all the places that lower maximum HP that I've managed
to find, but not spent much time looking for places that raise
current HP.
These changes might provide some more information. They don't rely
on sanity_check being enabled.
Issue #1252 is still open.
I recently realized that I've been editing sources in a terminal
window that was widened in order to fit curses borders for testing
something or other. That has resulted in some new wide lines in the
source. There were lots of old ones too.
This updates some source files to try to achieve the goal of 78
characters or less. As in the past, I've been inconsistent about
lines with 79 characters. Lines with 80 or more have been wrapped
or shortened (usually by trimming an end of line comment or removing
redundant parantheses, sometimes just by reducing the indentation
of the continuation portion of an already wrapped line).
I eliminated one instance of warning manipulation for non-constant
format string, and simplified stone_luck() where Ken had a silly
comment about the function argument's name.
Since wand of secret door detection now gives feedback even when it
fails to find anything, always discover it.
Some of the other zapnodir() wands had suspect discoveries.
Another byproduct of testing boulder pushing. If you kick a closed
door while polymorphed into a giant, always succeed in breaking the
door instead of maybe getting the Wham! or Thwack! failure result.
Noticed when testing boulder pushing into/out of shops yesterday:
a shopkeeper can "mutter incantations" and fracture a boulder in the
shop, transforming it to rocks. If hero owed shk for the boulder
(happens when it has been further inside the shop and then gets pushed
to the shop's free spot), it would disappear from the shop's bill and
hero would then owe for the resulting rocks (which cost more than the
boulder!). That seemed confusing, especially since neither Iu nor Ix
would show the rocks (which are on the floor rather than in invent;
the $ command reported the amount owed, but not what the item was).
When such fracturing happens move the boulder from the unpaid section
of the shop bill to the used-up section before creating the rocks,
which are no longer interesting.
The report is for 3.6.7: pushing a boulder into a general store adds
it to shop's inventory, but pushing it back out lets player remove it
for free. 3.7 has already fixed this; update its comments though.
Issue reported by ars3niy: having a pauper wizard #enhance bare-handed
fighting to basic caused the hero to learn all level 1 spellbooks.
Spellbook discovery for wizards when advancing skills is intentional,
to replace the old Luck-based chance of writing unknown books with
magic markers. (The Luck bias for wizards still applies for scrolls.)
Discovering spellbooks when advancing non-spell skills does feel wrong.
Change it to only happen when advancing spell skills.
This isn't pauper-specific, it's just a lot more noticeable in that
state.
There may be better ways to cope with this, but for the time being I'm
marking the issue 'fixed'.
Fixes#1278
For 'pauper', most roles start without any skills. However, strong
fighter types were starting with basic bare-handed combat/marital arts,
giving them a big advantage. Knights were starting with basic riding,
which is probably useless now that they have to acquire a saddle to
use it (see below). Take those initial skills away, producing an even
playing field.
Non-paupers get their initial skills without needing to spend any skill
credits (aka slots) on those. Give paupers 2 starting credits that
they'll be able to use once they acquire suitable weapons or spells
and train them up, so that once they're reasonably developed they won't
lag in skills compared to non-paupers.
Pauper knights were still starting with a saddled pony. Suppress the
saddle when the knight is a pauper.
Wizards start knowing a lot of spellbooks. Pauper wizards shouldn't.
Give most roles advance knowledge of one low level spell or other item.
It won't benefit them unless/until they find the corresponding item.
Reported by ars3niy, the curses interface could behave strangely on
the first turn if the 'pauper' option/conduct was specified.
There isn't any definitive flag indicating whether or not the game
has started. Since 'moves' has traditionally been initialized to 1
rather than to 0, there were several instances of
| if (moves <= 1 && invent != NULL)
being used to determine the starting state on the assumption that
once hero has inventory, the game has begun. Introduction of the
'pauper' option made the test for non-Null invent become unreliable.
For paupers, the program would behave as if the game hadn't started
yet until the player finally made a time-consuming move.
This changes compile-time initialization of 'moves' from 1 to 0,
then sets it to 1 when initial inventory would be bestowed (even
when 'pauper' inhibits that). That's probably not the best place
for it, but testing for 'moves==0' now should produce an identical
effect as 'moves<=1 && invent!=NULL' used to accomplish.
It would have been much simpler just to give paupers 1 gold piece,
or perhaps one rock, in place of usual starting gear so that their
initial inventory wouldn't be empty, but the moves+invent way of
checking for start-of-play has always bothered me.
Should 'pauper' be preventing 'nethack -X' from giving its starting
wand of wishing? Conducts and explore mode don't really overlap so
maybe it doesn't matter.
Fixes#1275
The old secret door detection just redisplayed locations with
discoveries (secret doors and traps, mostly). Somewhere along the
line it was augmented to find hidden monsters and to deliver one or
two messages reporting how many things had been discovered. Now it
has been augmented again, to find trapped doors and chests, and to
supply a message when the detection attempt fails to find anything.
More substantially, it highlights the relevant locations as they're
found, before the feedback message(s).
Initially I was using tmp_at() to mark all significant locations,
but that required --More-- and for player to acknowledge it when
detection was done. That would probably be ok for wand of secret
door detection and spell of detect unseen, but it would be a hassle
for ^E. It's been revised to use flash_glyph_at() [previously only
used when ^G creates unseen monsters, I think].
The new behavior seems to be working reasonably well. For curses,
the 'timed_delay' option must be set. flash_glyph_at() calls
flush_screen() between its output and nap in each cycle of multiple
flashes, but that evidently isn't sufficient for curses. Maybe
curses init should just force on 'timed_delay'.
I've left the tmp_at() stuff in. We might want to modify things to
use it instead of flash_glyph_at() when the accessibility flag is
set. Its current compile-time selection won't be adequate though.
do_clear_area() runs a callback over each point in a square around
a center point. When executed near the edge of the map, it clips
the square to avoid going over that edge. But on the left side,
it was clipping to column 0 rather than 1, so running the callback
routine on column 0 even though that isn't part of the level. This
bug doesn't seem to have caused any problems though.
magic_map_background() would overwrite remembered objects and traps.
That meant discovery of secret corridors by secret door detection
or ^E would forget embedded objects at their locations.
^E and wand of secret door detection used to just update the map
without any other feedback, but were changed post-3.6 to issue a
message about what things are being discovered. But the message is
misleading if [some of] the things revealed are obscured by objects
or by monsters. Presumeably by regions too.
If player uses the 'm' prefix before the #vanquished command when
the vanquished monsters list has fewer than two types so far,
select the preferred sort for #vanquished even though it won't be
applicable yet.
Also, when prompting about vanquished monsters during end of game
disclosure, where an 'a' response is given special meaning, use
"[ynq]" instead of "[ynaq]" if there is only one type of monster
vanquished. It's skipped altogether when the list has zero types
and there's no point in picking sort order when there is just one
type. The player can still answer with 'a' when [ynq] doesn't show
that (for tty and curses at least, probably X11); 'a' will end up
behaving as 'y' in that case.
Explicitly sort and label Riders before major demons when displaying
vanquished monsters with sort-by-class. They're lumped in with '&'
but they aren't really demons.
When looking at a monster that's inside a gas cloud, include that
fact in the output for farlook and for probing. When the monster
being examined is sensed rather than seen, you'll sense the presense
of the cloud as well as the monster even if the cloud can't be seen.
Do likewise for self when using look-here (':'). Bonus fix: zapping
wand of probing at self while engulfed reported that you were just
held by the engulfer.
Also fix an old comment typo/thinko.
Support tab separation for the region portion of #timeout output.
This works ok under Qt. However, the output from #timeout uses a
fixed-width font so tab separation isn't necessary.
No idea how well it will work for mswin.
Some_Monnam() returns "Someone" or "Something", not "Someone" or "It".
Removing the redundant '&& uchain != NULL' test shouldn't produce any
change in behavior.
Testing the shopkeeper speed change, I noticed that zapping the shk
with speed monster made her angry. Since being hasted is beneficial
for the target, don't become angry.
Allow farlook/quicklook to step through all engravings--corridor
ones as well as room ones--with repeated '`' when picking location
with getpos(), similar to how repeated '^' goes through all traps
no matter what display character they use.
It isn't possible to look at corridor engravings by using their
default symbol '#'. It is possible by using 'a' for "anything of
interest" but that matches lots of other stuff.
This tries to add an NHDT tags line to sym.h. That was followed by
'git nhadd' which did stage it for commit, but date/branch/revision
tag expansion isn't working. I did something similar to defsym.h
about 5 weeks ago; that one worked and I don't recall having needed
to do anything special.
From a change made about two and half months ago: eating a pyrolisk
egg tried to use it up from inventory even when it was on the floor.
That would trigger an object lost panic.
When hero was swallowed and a temporary region at swallower's spot
expired, hero was told "the gas cloud around you dissipates". This
just suppresses the message rather than changing it into "the gas
cloud around <engulfer> dissipates".
Various bits tried while flailing about with map display of monsters
in visible regions. The newsym()/mon_overrides_region() part is
definitely an improvement because the logic about whether to show a
monster in a region or just the region wasn't easy to comprehend and
was even harder to extend.
I'm not sure whether the _map_location() part is necessary.
This fixes the bug where a monster displayed instead of a gas cloud
because the hero was next to it didn't revert to gas cloud when hero
moved and was no longer next to the monster.
It is possible to have a known trap be at the same location as a gas
cloud region. When paranoid_confirm:trap is set, ask for confirmation
about entering the region before confirmation about entering the trap
since the map will be showing the region rather than the trap.
Dual confirmations will be annoying but not new. Before this change,
it would ask about entering the trap, and if the answer was yes, it
would ask about entering the region. The situation seems to be too
rare to warrant implementing a single combined confirmation, and the
code to accomplish that would likely be messy.