gcc has recognized various "magic comments" for white-listing
occurrences of implicit fallthrough in switch statements for
a long time:
The range and shape of "falls through" comments accepted are
contingent upon the level of the warning. (The default level is =3.)
-Wimplicit-fallthrough=0 disables the warning altogether.
-Wimplicit-fallthrough=1 treats any kind of comment as a "falls through" comment.
-Wimplicit-fallthrough=2 essentially accepts any comment that contains something
that matches (case insensitively) "falls?[ \t-]*thr(ough|u)" regular expression.
-Wimplicit-fallthrough=3 case sensitively matches a wide range of regular
expressions, listed in the GCC manual. E.g., all of these are accepted:
/* Falls through. */
/* fall-thru */
/* Else falls through. */
/* FALLTHRU */
/* ... falls through ... */
etc.
-Wimplicit-fallthrough=4 also, case sensitively matches a range of regular
expressions but is much more strict than level =3.
-Wimplicit-fallthrough=5 doesn't recognize any comments.
Plenty of other compilers did not recognize the gcc comment convention,
and up until now the compiler warning for detecting unintended
fallthrough had to be suppressed on other compilers. That's because the code
in NetHack has been relying on the gcc approach, and only the gcc approach.
The C23 standard introduces an attribute [[fallthrough]] for the
functionality, when implicit fallthrough warnings have been enabled.
Several popular compilers already support that, or a very similar attribute
style approach, today, even ahead of their C23 support:
C compiler whitelist approach
--------------------------- -------------------------------------
C23 conforming compilers [[fallthrough]]
clang versions supporting
standards prior to
C23 __attribute__((__fallthrough__))
Microsoft Visual Studio
since VS 2022 17.4.
The warning C5262 controls
whether the implict
fallthrough is detected and
warned about with
/std:clatest. [[fallthrough]]
This adds support to NetHack for the attribute approach by inserting a
macro FALLTHROUGH to the existing cases that require white-listing, so
other compilers can analyze things too.
The definition of the FALLTHROUGH macro is controlled in include/tradstdc.h.
The gcc comment approach has also been left in place at this time.
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
Add enlightenment feedback for Sunsword's blocking of becoming blind
from light flashes. It uses an extra property so that wizard mode
can report the reason.
EDITLEVEL is being incremented, so existing save and bones files are
invalidated.
timeout.c:550:1: warning: no previous prototype for ‘region_dialogue’ [-Wmissing-prototypes]
550 | region_dialogue(void)
| ^~~~~~~~~~~~~~~
../win/curses/curswins.c: In function ‘curses_destroy_win’:
../win/curses/curswins.c:202:33: warning: variable ‘dummyht’ set but not used [-Wunused-but-set-variable]
202 | int mapwidth = 0, winwidth, dummyht;
| ^~~~~~~
Like stuck-in-wall, there might not be any place to move the hero
in order to escape a poison gas cloud. That could result in "fix
all troubles" becoming stuck in a loop. 3.6.something fixed the
stuck-in-wall case by temporarily conferring Passes_walls. Fix the
in-poison-region case by temporarily conferring Magical_breathing.
Not adequately tested...
I don't think that this fixes "#K4252: NH 3.7 Prayer Bug" where the
game hung during a couple out of scores of prayers. I didn't see
any other fix-trouble cases that seemed likely to remain unfixed
and end up with repair attempts retrying.
Show visible regions among the other timed events. Turn number is
relative rather than absolute. Location is the internal bounding box
which tends to cover more area than just the gas cloud spots.
When multiple regions are present (common on Plane of Fire), they're
listed in arbitrary order. It would be better to order them by
timeout or by location or both, but the extra effort to do that seems
unjustified.
The g? structs had a mix of variables that were written to
the savefile, and those that were not.
For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.
This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.
Details:
gb.bases -> svb.bases
gb.bbubbles -> svb.bbubbles
gb.branches -> svb.branches
gc.context -> svc.context
gd.disco -> svd.disco
gd.dndest -> svd.dndest
gd.doors -> svd.doors
gd.doors_alloc -> svd.doors_alloc
gd.dungeon_topology -> svd.dungeon_topology
gd.dungeons -> svd.dungeons
ge.exclusion_zones -> sve.exclusion_zones
gh.hackpid -> svh.hackpid
gi.inv_pos -> svi.inv_pos
gk.killer -> svk.killer
gl.lastseentyp -> svl.lastseentyp
gl.level -> svl.level
gl.level_info -> svl.level_info
gm.mapseenchn -> svm.mapseenchn
gm.moves -> svm.moves
gm.mvitals -> svm.mvitals
gn.n_dgns -> svn.n_dgns
gn.n_regions -> svn.n_regions
gn.nroom -> svn.nroom
go.oracle_cnt -> svo.oracle_cnt
gp.pl_character -> svp.pl_character
gp.pl_fruit -> svp.pl_fruit
gp.plname -> svp.plname
gp.program_state -> svp.program_state
gq.quest_status -> svq.quest_status
gr.rooms -> svr.rooms
gs.sp_levchn -> svs.sp_levchn
gs.spl_book -> svs.spl_book
gt.timer_id -> svt.timer_id
gt.tune -> svt.tune
gu.updest -> svu.updest
gx.xmax -> svx.xmax
gx.xmin -> svx.xmin
gy.ymax -> svy.ymax
gy.ymin -> svy.ymin
Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
gf.ftrap, gl.light_base, gt.timer_base
In 3.6.2 parts of the wakeup code were merged together, and this
caused pets consider any noise made by the hero - such as hitting
iron bars or digging - as whistling for them to come to the hero.
Change it to only consider actual whistling and ringing a bell.
If moving on ice causes the hero to hurtle an extra step in a random
direction, don't allow that to be backward to where hero started.
Also, if hero is in grid bug form, only allow hurtling forward.
It was allowing slips in a diagonal direction, which seems wrong
for grid bug, and even when it slipped in an orthogonal direction,
buffered screen updating made the combined step+hurtle appear to be
a single diagonal step.
I'm not a fan of this seemingly simple change. The hurtle/second
step comes after the "you slip on the ice" vs "you slip off the ice"
messaging and might put the hero in a location which contradicts it.
Update some potential weight issues. Eggs won't hatch when in
containers so they weren't affected but add some bulletproofing.
Corpse revival from inside containers was already ok too, so
effectively there's no change except for making container_weight() be
global instead of local to mkobj.c.
There were few places where the object weight was not updated:
- container when the contents were broken by impact
- starting to eat but getting stopped by rotten food
- using lua, container when putting an object inside it
- when a single egg of a larger stack hatched
New timed sanity checking trying to validate a timer's map location
can't locate a timed object (in this case, an egg with a hatch timer)
inside a container carried by a migrating monster.
The case of the object being carried directly by a migrating monster
was handled, but one inside a container wasn't.
and having temporary stoning resistance timeout before finishing.
Issue reported by Umbire: hero was able to finish eating Medusa's
corpse safely after getting the message about no longer being
protected against stoning that is given when temporary resistance
times out.
The eating code was extending temporary resistance--when eating
something protected by such--to avoid just that. I thought this
was probably a message sequencing situation but it turns out that
the code was using touch_petrifies() to test the meal. It should
use flesh_petrifies() instead; Medusa doesn't pass touch_petrifies().
I didn't figure that out until after rewriting how the duration is
extended. The old way probably would have worked as desired with
the revised petrify test but I'm checking in the new version anyway.
Fixes#1186
Two variations:
IndexOk(idx, array) validate that idx is a valid index into the array
IndexOkT(idx, array) validate that idx is a valid index into the
array, excluding the final Terminator element
Four kinds of timers are defined but only two have ever been used.
Have sanity checking complain if the other two occur or if 'kind'
doesn't match any of the four.
Also, replacing a perfectly normal use of isok() with an inline test
just to pacify static analysis feels like a slippery slope, so handle
that a little differently.
I reordered the shrink_glob timer to put all object timers together.
Unfortunately that warrants incrementing EDITLEVEL which invalidates
existing save files.
src/timeout.c(2033): warning: Reading invalid data from 'gl.level.locations'.
Analyzer couldn't tell that isok(x, y) had validated x and y to be
safe indexes into gl.level.locations[x][y].
Code it a bit differently, so that the static analyzer becomes perfectly
aware that the indexes are, indeed, in range.
Moving over at item that's resting on ice gives a message about there
being ice present and then about the item, whether mention_decor is On
or Off. With it On, you'll get a message about being back on solid
ground as soon as you leave the ice. With it Off you wouldn't get
that at all if not levitating; that's the basic no-mention_decor
behavior for ice. However, if you were levitating, you would get a
delayed "back on solid ground" message when moving over some other
object, which might occur quite a bit later. Autopickup handling is
calling describe_decor() when the hero is levitating and some of that
wasn't appropriate for no-mention_decor.
This issue has been present since I first implemented mention_decor,
not introduced by recent back_on_ground() changes.
Fumbling makes the hero fall from the saddle, but the justification was
weak if the only fumbling source is riding over ice (the messages were
things like "you drop the reins" which made more sense from magical
fumbling). Make all fumbling from ice alone go into the ice-specific
"slip on the ice" block and add a chance to fall from your mount there.
If fumbling from another source while riding on ice, the hero will
always fall from his steed, since that's what happens on normal floor --
ice had actually been reducing this chance.
Change dying in lava to attempt life-saving at most twice. The first
time might be via amulet or via declining to die. The second time
can only be via declining to die after failing to teleport to safety
the first time, but could happen in explore mode as well as in wizard
mode, either interactive or fuzzer.
If the hero dies twice without ending the game, confer temporary fire
resistance and water walking so that other actions can be attempted.
After 5 turns without getting away from the lava or doing something
to acquire those capabilities, the hero will be subject to falling in
again.
Then the whole cycle might repeat, even many times, but the fuzzer
will eventually choose ^V or #wizmakemap and escape. Players in
explore mode will either figure out a way to get out of it or
eventually have to give up but can try as many times as they like,
not that much different than being cornered by a deadly monster.
I was working on this at the time 3.6.0 was released and set it aside
until later. Later has finally arrived. Redo the Blind, Blinded,
Blindfolded,&c macros to make more complete use of intrinsic property
handling. Blinded was being treated as a number which could be added
to or subtracted from; now that has to be done via TIMEOUT mask
because it has FROMOUTSIDE (OPTIONS:blind) and FROMFORM (poly'd into
!haseyes() form) bits included. Object definitions for blindfold and
towel now specify the BLINDED property; overriding blindness via the
Eyes of the Overworld is accomplished via props[BLINDED].blocked.
Code generated for the scores of Blind and !Blind tests throughout
the program should be smaller.
One bug that has been fixed is that putting on the Eyes of the
Overworld cured permanent blindness (from OPTIONS:blind). The
u.uroleplay.blind flag was cleared and stayed so after taking them
off. Putting the Eyes on still breaks blind-from-birth conduct but
now blindness will resume when they are removed.
This was untested at the time it was set aside and is only lightly
tested now. A large number of the changes here are just to switch
from Blinded to BlindedTimeout for current timed value and to call
set_itimeout() for setting a new value.
Extend "killed by the touch of death inflicted by <monster>" to buzz().
"Killed by a bolt of cold" becomes "killed by a bolt of cold zapped by
<monster>" or "killed by a blast of cold" becomes "killed by a blast
of cold exhaled by <monster>" and so forth.
More work than expected; the zap code isn't passed enough context.
BZ_M_WAND() was producing the wrong value for wands zapped by monsters.
A bug report from ten and half years ago...
If a carried egg hatches, the message is
|<foo> drops from your pack.
and if tame, is followed by
|Its cries sound like {mommy,daddy}.
The latter was issued even when <foo> has no speech capability.
Replace "its cries sound like" with "its <vocalize>ing sounds like"
for suitable value of <vocalize>.
This adds two new monster sounds, MS_BELLOW and MS_CHIRP, also two
new sound effect codes, se_chirp and se_croc_bellow.
We had MS_SILENT for crocodile. On wikipedia, crocodile is described
as the most vocal reptile. Adult males make a load bellowing noise
and hatchlings make a chirping noise.
This changes crocodile, titanothere, and baluchitherium from MS_SILENT
to MS_BELLOW and baby crocodile from MS_SILENT to MS_CHIRP. Chirp
might be appropriate for lizards and lizard-like amphibians but I've
left those as MS_SILENT.
[Noticed but not changed: lizards and lizard-like amphibians aren't
flagged as oviparous. Shouldn't they be?]