Experience-level and experience-points, if enabled, could be
highlighted via 'up' or 'changed' rules in initial display after
restore. I tried 'down' rule too but didn't produce with that.
I don't understand what was going on but was able to reproduce it
and then fix it via the trial and error method....
Disarming a chest trap was setting obj->tknown = 0 even though the
hero just discovered that it isn't trapped.
Triggering a chest trap behaved similarly. Since there are no
repeating chest traps, hero should know that the chest whose trap
just went off is no longer trapped.
chest_trap() didn't document its return value but was clearly meant
to return True if the chest was destroyed. It didn't handle that
correctly when the chest was being carried. However, none of the
callers actually use the return value. [This fix tracks whether the
chest gets deleted; a better fix would be to destroy an exploding
chest even when it is being carried.]
If 'autounlock' is set to test a chest for traps, skip "check for
traps?" when tknown is set; go directly to "disarm trap?" if the
chest is trapped, skip that too if it isn't.
If wand of probing hits a chest, set the tknown bit.
Issue reported by elunna: Using the 'F' prefix against a displacer
beast prevented swapping places.
This doesn't use the suggested fix. It is quite short but there is
a large diff due to change in indentation and reformatting several
comments because of that.
Attacking a displacer beast either with or without 'F' might miss,
hit, or swap places. It won't "harmlessly attack thin air."
Fixes#1377
Protect carried items as well as hero when carrying the Mitre of
Holiness. Already handled when wearing that artifact.
This might make it be too strong. At the time that it was given
the carrued attribute, there was no such thing as carried items
providing any protection to other carried items.
"You have disabled loading of bones levels" (during play) and
"You disabled loading of bones levels" (end of game disclosure)
both clearly refer to the player rather than the hero.
"You have never encountered a bones level" is accurate for current
hero but not necessarily accurate for the player. Rephrase it.
Also, if OPTIONS=!bones is set and the hero just died, extend
"You disabled loading of bones levels" during disclosure to
"You disabled loading and storing of bones levels" (even in the
case where bones wouldn't be saved anyway).
Most recent version of XQuartz, same as before. Unfortunately,
newer version of macOS => newer version of Xcode and its command
line tools => newer version of clang => emulating newer version of
gcc which defaults to a more recent version of StdC, I suppose, or
perhaps our hints are specifying that. Whichever, it has resulted
in a bunch of complaints about XtOffset() used in win/X11/winX.c:
|warning: performing pointer subtraction with a null pointer has\
undefined behavior [-Wnull-pointer-subtraction]
Adding -wno-null-pointer-subtraction to X11FLAGS silences them,
but that would require figuring out which versions of gcc and
clang added -Wnull-pointer-subtraction and its negation. Revising
XtOffset() to include the ptrdiff_t casts eliminates the warnings,
avoiding the need for version conditionals to deal with X11FLAGS.
Reported by k21971: applying an axe toward a location that contained
both a tree and a boulder (or statue) would use the axe to break the
boulder/statue rather than chop down the tree.
Different code is used to finish the dig/chop than is used to decide
whether the tool is appropriate for its target.
Fixes#1383
Issue reported by Umbire: if a mind flayer got turned to stone by
hitting a hero who is polymorphed into a cockatrice and the first
tentacle drain missed but a subsequent one hit, any remaining ones
would keep being applied even though the mind flayer was dead.
This works but doesn't feel right to me. A more substantial change
to mhitm_ad_drin() didn't work as expected so I've settled for this.
Fixes#1378
Issue reported by elunna: nethack has become confused about
resistances held by poly'd hero.
resists_xxxx() got changed to check worn and carried equipment
so was no longer accurate for use when changes shape.
Fixes#1382
When hunting for player's run-time config file under MacOS/OSX,
nethack looks for .nethackrc (or $HOME/.nethackrc), then if not
found it looks for
"$HOME/Library/Preferences/NetHack Defaults", and finally for
"$HOME/Library/Preferences/NetHack Defaults.txt".
When none of those exists, the last choice has been being left in
configfile[] and can get used in messages.
The menu for entering the tutorial includes a tip about setting
OPTIONS=!tutorial in the config file, but it was showing the third
choice rather than the first when none of them are found. Change
config file name setup to remember the first name rather than the
last when it represents a non-existant/not-yet-existent file, so
that the tip recommnends the standard Unix name rather than the
Mac-specific one.
Report the effect of suit and/or robe on spell casting during
attribute enlightenment.
Doesn't attempt to include other armor slots. That's complicated
and would end up being too verbose.
Issue reported by elunna: the definition of the Mitre of Holiness
specifies that carrying it should confer fire resistance but that
didn't work.
The Mitre's definition (added in 3.1.0) has always included that,
but such a capability had never been implemented. Wearing it didn't
confer fire resistance either--its definition doesn't bother to
specify a 'defend' attribute since the 'carry' one should cover that.
This adds carrying capability for damage types fire, cold, sleep,
disintegration, electrity, poison, acid, and petrification. Fire is
still specified by the Mitre; none of the others are currently used.
Fixes#1362
> if (strlen(simpleoname) > BUFSZ - sizeof "the ")
> simpleoname[sizeof "the "] = '\0';
The second line should have been
| simpleoname[strlen(simpleoname) - sizeof "the "] = '\0';
but fixing that isn't adequate. The BUFSZ limit is not valid when
dealing with object names since xname() leaves room for a prefix so
doesn't return the start of a BUFSZ-sized buffer.
Strangely enough, the complaint that caused me to add those two lines
isn't being triggered any more. Some other change at the same time,
perhaps splitting
Strcpy(simpleoname, obufp = the(simpleoname));
into
obufp = the(simpleoname);
Strcpy(simpleoname, obufp);
pacified the analyzer. However, it didn't resolve the valid complaint
that inserting "the " might result in overflow.
I've added a comment about simpleonames(), ansimpleoname(), and
thesimpleoname() about the possible overflow, but I don't think that
such overflow can actually happen when user-applied object name is
being suppressed.
I got confused and thought that this one (actually pair) was more
complicated than it actually is. have_mixed_leadin is used in an
ordinary way, but resetting it to false happens in spots where it
can't be used again. The analyzer complains that the assignments
don't do anything useful.
When testing the analyzer lint fixes for pager.c, I noticed that //
wasn't finding the data.base entry for stairs when examining the up
stairs on level 1. It is labelled "branch stairs up" which doesn't
match "stair*".
This construct triggered several complaints about passing Null to
Strcpy(simpleoname, obufp = the(simpleoname));
Changing that to
obufp = the(simpleoname);
Strcpy(simpleoname, obufp);
prevents it, but the original complaint is bogus and the "fix"
doesn't do anything to deal with Null arguments.
A couple of other changes introduce different code in order to get
different behavior. I updated from llvm-16 to llvm-19 but didn't
eliminate any of the spurious complaints.
Clear "next" boulder so that when pushing a pile of boulders, only
the first message for each of the 2nd, 3rd, &c will be formatted as
"next boulder". If any of them trigger additional messages, those
messages will use normal "boulder".
makemon() has a 1% chance to bestow a worn saddle when creating any
rideable monster. If that chance kicked in on a knight's starting
pony, an extra saddle would end up being created but not worn nor
in inventory nor on floor so not be freed when the game ended.
That 1% chance also overrode saddle suppression for pauper knights.
There wouldn't be any extra saddle but their pony could start with
one, against intent.
Have makedog() (which is only used for starting pet) tell makemon()
to suppress inventory when creating the initial pet.
Overzealous change yesterday. For use_defensive(), the unicorn
horn case already has guards for Null item and the added one
issues bogus panic() when a unicorn or ki-rin uses its own horn.
I'm not really sure about this one. insert_branch(branch,) is
specified as not accepting a Null pointer and doesn't have any
defense against it, but the know level setup seems to allow a null
pointer through. I'm not sure whether this is the right fix.
The missing break meant that executation fell through to the default
case and reset xlocale and ylocale to 0. The comment states that
this is for the fuzzer; I have no idea whether this fix matters to it.
Verifying that strlen(string) isn't too long, then allocating and
copying strlen(string)+1 draws a complaint about strcpy() overflowing
its output buffer.
Not an issue for regular play, but could matter for config file and
sysconf manipulation.
Picked arbitrarily; there weren't any unresolved analyzer complaints
for trap.c. I wonder why the onefile analysis isn't complaining here.
'in_sight' may have been relevant before the trapeffect_xyz() code
was split apart, but it isn't useful for trapeffect_hole() despite
the comment about it.
release_holding_trap() is fairly convoluted and the complaints being
addressed here were relevant.
This cleans up analyzer feedback in shk.c, based on the set of
warnings specified by hints/MacOS.370 and the lower level hints it
applies, rather than anything specified during periodic 'onefile'
processing.
shk.c is the only file I've analyzed, to try again to figure out
how to suppress the old complaint that has been causing a special
case in Genonefile. It isn't triggering during my testing but that
might be due to something in use by onefile but not by normal hints.
I'm running ccc-analyzer from llvm-16; I don't know whether that
matches Genonefile.
The new EXTRA_SANITY_CHECK for a monster mimicking a monster. It
falsely triggered if the hero was hallucinating. Just add an
assertion that the monster index is within valid range.
The report (sent directly to devteam) stated that the bump-into-mimic
code might crash when bumping into a mimic that is masqueraing as
some other monster. Mimics don't actually do that, but the Wizard
of Yendor mimics another monster via Double Trouble. All I got from
it though is
|Wait! That's <other monster>!
which won't crash but is a fairly useless message.
This changes it to be
|Wait! That <other monster> is <the Wizard of Yendor>!
which seems a bit bland but provides useful information.
Use ESHK(shkp)->bill_p consistently. The bill[] array field is used
to initialize the bill_p pointer field rather than be used directly
when manipulating shop bills.
While in there, get rid of some '#if DUMB' from pre-standard C days.
I couldn't reproduce the reported problem but the backtrace suggests
that defsyms[monst->mappearance] was probably out of bounds so that
nh_snprintf() got bad data. That might conceivably happen if the
glyph didn't match the mimic's mappearance, but I not sure how that
would occur.
This avoids using mappearance as an index into defsyms[] and should
give an impossible if that situation does come up.
Commit ba731a346b "fix shop steal when
teleporting your engulfer" mentioned that there was no longer any
message given if engulfer+hero got teleported. Add such. It is a
bit lame but the situation is rare enough that it should suffice.
Issue reported by ostrosablin: having Kick enabled as one of the
values for the 'autounlock' option succeeded it prompting "kick it?"
when walking into a locked closed door, but answering "yes" behaved
the same as answering "no".
There's bound to be a better way of fixing this, but this works.
Fixes#1360
If water walking boots haven't been discovered yet and underwater
hero rises to the surface when putting a pair on, discover them.
(Sinking while removing such on water already discovers them.)
Aka issue #1339 take II
For hero-owned container with some unpaid items, the itemized
shopping bill had a spurious index into the traditional shopping
bill (since it wasn't in that bill due not being unpaid). When mixed
with unpaid items that weren't in the container, that could cause
bill corruption while updating the traditional bill during payment,
leading to impossible warnings.
Fixes#1339Fixes#1350
Issue reported by ars3niy: with the relatively new container
handling, buying multiple items when some were inside a container
sometimes triggered impossible "unpaid_cost: object wasn't on any
bill" warnings and not buy all intended items. Once that occurred,
subsequent inventory display would repeat the warning.
A couple weeks back, I managed to produce a save file which would
reproduce the problem when 'p' was issued, but failed to figure
out why that was happening. I accidentally deleted that save file
and it took quite a lot of further attempts to get another one.
I still don't understand why this fix is needed, but with it in
place the save file no longer triggers any problems. I'm marking
the issue fixed but that could be premature.
Fixes#1339
Issue reported by k21971: winter wolf cub and hellhound pup were
defined with alignment -5 (chaotic) while winter wolf and hellhound
were 0 (neutral).
K2 suggested that winter wolf plus cub both be neutral and hellhound
plus pup both be chaotic but I've gone another way: both cub and
pup are now 0 and both adults are -5.
Fixes#1340
Various bits I had in progress before Michael's commit.
Mainly forget engravings when bones are saved instead of leaving them
flagged as seen for the next hero who gets the level.
Issue reported by elunna: the message given when zap_over_floor()
hits iron bars with lightning or acid was substituting a couple of
words or phrases in the wrong order, resulting in
|The {melt|dissolve} iron bars somewhat but remain intact.
when the iron bar location is flagged as non-diggable. It should be
|The iron bars {melt|dissolve} somewhat but remain intact.
Not mentioned: the corresponding message for locations that aren't
flagged as non-diggable used "melt" unconditionally. Change it to
keep "melt" for lightning but switch to "corrode away" for acid.
Fixes#1342
A fix in Janurary to avoid appending engraving text or headstone
text when examining a map location where a monster or object covers
the engraving or headstone inadvently broke the /e and /E variations
of the '/' command, which is intended to list such text even when
covered.
Issue reported by loggersviii: attempting #untrap from an adjacent
doorway can move the hero diagonally out of the doorway.
A followup comment by elunna pointed out that a monster's attack that
results in knockback can produce similar result.
Fixes#1305
Issue reported by elunna: if the 'fireassist' option is on and the
quiver contains ammo, 'f' while wielding an aklys switches to the
ammo's launcher instead of throwing the aklys.
Fixes#1337
Issue reported by ars3niy: pets with reflection or ranged attacks
would only attack floating eyes when rolling the 10% random chance
that other pets have even though they could have always safely
attacked.
This fixes the situation for melee attacks by pets who have
reflection.
dog_move() is too complicated for my feeble brain to cope with the
ranged attack aspect. Pets still won't use ranged attacks against
floating eyes.
With the fix for reflection, I discovered that silver dragons
would be subjected to floating eyes' passive paralysis even when
their breath attack was suppressed. (It wouldn't impact them, due
to reflection, but the message about the floating eye being hit by
its reflected gaze was being delivered without being preceded by
any message since no attack had taken place yet.) This fixes that.
\#1336 is still open
Merge the recent change in the effect of blessed scroll of taming on
already tame monsters with the earlier change of any taming on already
tame monsters. Non-blessed has a chance of boosting monst->mtame by 1
when it is less than 10, more likely the lower the current value is.
For blessed, boost by 2 after that, so possibly by 3 if it is very low.
Make spell of charm monster when skilled or expert in enchantment
spells behave the same as blessed scroll of taming. [I'm not too sure
about this; it may make the spell too powerful.]
When a mimic in door form is hit by a wand of locking or wand of
opening or corresponding spell, bring it out of concealment like
was recently done for being zapped while in chest form. And give
some feedback rather than just changing the mimic's form to 'm'.
Give more detailed feedback when bumping into a mimic while moving.
Issue reported by elunna: sleeping mimics can grab the hero, and
zapping a concealed mimic with a wand of sleep describes the target
as a mimic but doesn't bring it out of concealment.
The grab-when-asleep case is reasonable. It's a reflexive counter-
attack by a magical creature. And the mimic wakes up in the process.
But the mimic wasn't being brought out of concealment. Do that.
Unconceal mimics hit by wand of sleep unless already sleeping.
Fixes#1299
Issue reported by youkan700: shape change anomalies. Shapechangers
could change shape despite active protection-from-shape-changers if
hero wore two rings of protection from shape changers and took one
off. Shapechangers who migrated to a not-yet-visited level that
eventually got visited with protection from shape changers in effect
would be stuck in their current shape, even if the PfSC attribute
got toggled off and back on.
The issue included suggested fixes and those are what I've used. I
noticed a third case that only applies to wizard mode: if player
used #wizintrinsic to set a timed value for PfSC, monsters wouldn't
resume changing shape after it timed out, unless/until it got toggled
on and back off via a PfSC ring or hero left the level and returned.
Fixes#1312
If a vampire in fog cloud form moves under a closed door and then
before moving further gets killed and revives in vampire form,
destroy the door instead of moving the vampire to a nearby open
spot (which might be a distant spot if the map is crowded). If the
door is trapped, explode the trap. That will damage the vampire but
usually not by enough to kill it.
This probably ought to be generalized to be done for any shape change
at a closed location but I ran out of gas.