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.
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
The new change to reset discoveries and monster-stats when exiting
the tutorial used dynamic data which wouldn't be freed if player
used #quit and declined to resume the regular game.
It turns out that such a leak was already present for start-of-game
inventory that gets stashed away during the tutorial.
In both cases, it could happen at most once per game so wasn't a big
deal as far as memory leaks go.
Reported by AndrioCelos, a handful of objects in the tutorial can
be discovered via use, and such discoveries were carrying over to
normal play when the tutorial ended.
This causes the hero to forget such discoveries. The player will
still be able to remember them. The proper fix would be to discard
the initialized but not-yet-started game when entering the tutorial
and then start a whole new one when exiting so that saving and
restoring game state would become unnecessary. This doesn't do that.
This also causes monster birth and death statistics to be reset when
exiting the tutorial. Affects the #vanquished command and potentially
extinctionist play.
Closes#1134
- fix stack imbalances
- call panic() instead of nhl_error() if L==0 to prevent immediate crash
- drop unused argument prep in get_nh_lua_variables
- change nhl_pcall_handle to clean up stack after calling impossible()
- don't force full garbage collection runs
- don't collect garbage to do memory usage checking
- remove unnecessary stack resets
Run GC on the themeroom lua states, as they're not freed
until end of game.
Allocate the exact amount of data we use instead of padding it.
Free our state data after closing the lua state; doing it
the other way is the way to madness, which was kept at bay
by the padded allocation amount.
Commit 7a533a911c about three weeks
ago reordered a couple of timers. The list of timers in nhlua.c was
overlooked at the time.
The theme room "Ice room" was affected. I'm surprised that sanity
checking while running the fuzzer didn't notice and complain.
- add nhl_pcall_handle() to wrap all nhl_pcall calls that didn't check
return value and either panic() or impossible()
- add --loglua (unix only) to dump Lua memory and steps info to livelog
- remove old logging
- set memory and step limits on all Lua VMs
Silence a bunch of complaints from heaputil about freeing Null
pointers. The C standard allows that but it makes the data collected
about mallocs and frees not match up when nethack has MONITOR_HEAP
enabled.
Instead of just accepting an attribute, it's now possible to
use a color, or both color and attribute, for example:
OPTIONS=menu_headings:inverse
OPTIONS=menu_headings:red
OPTIONS=menu_headings:red&underline
Default is still just inverse.
This lets the player change the menu heading color without
needing to use menu colors for them.
Also makes it so the core uses NO_COLOR instead of 0, for all
the menu lines which don't have any prefedefined color.
Tested for tty, curses, x11, qt, and win32
Using apply to unlight a lit potion of oil makes it unlit, removes
it from inventory, and then re-adds it to try to force it to merge
with other potions of oil. If it was wielded and the other potions
were quivered, the game would panic. When merging, they get forced
into the weapon slot in preference to the quiver slot.
Unwearing it before freeinv+addinv would solve this but also leave
the hero with nothing wielded, even if it didn't merge with another
stack. Instead, don't try to merge if the potion being unlit happens
to be worn.
3.6.x was subject to this too and the fix is small+isolated but the
situation is so uncommon that I haven't bothered backporting it.
Applying a lump of royal jelly and then not picking anything to rub
it on had a similar problem. It also panicked if the applied lump
was wielded and other lumps were quivered. The fix is different
because the stack it gets split from during apply is known. This one
doesn't impact 3.6.x; applying jelly to eggs wasn't implemented yet.
While running the tutorial, the Save command is disabled. When the
tutorial was extended to two levels, stashing and restoring the
hero's equipment stopped working as intended if player entered the
second level. The attempted fix for that broke re-enabling Save
even if the player left the tutorial without entering its second
level.
This seems to fix things, but I'm flailing around with barely a clue
here. A couple of simpler attempts didn't work and I haven't figured
out why, so this is a bit more complex than what I wanted.
Reorganizing nhl_callback() isn't part of the fix, just avoids use
of some redundant code.
Reported by Noisytoot: going from level tut-1 to tut-2 returned the
hero's starting equipment too soon, and exiting the tutorial from
tut-2 let the hero keep any equipment acquired within the tutorial.
Entering and leaving the tutorial was being handled by lua code in
the level description of tut-1 and adding a second level messed that
up. I didn't see any way of handing that with level-specific lua
code so I made it become the core's responsibility. gotolevel()
knows when the hero is moving from one dungeon branch to another so
it can recognize entry to or exit from the tutorial easily.
While fixing this, prevent #invoke of the Eye of the Aethiopica from
offering the tutorial as a candidate destination (was feasible if it
had been entered at start of game).
Not fixed: levels visited in the tutorial become part of #overview.
Show location as "Tutorial:1" instead of "Dlvl:1" on status lines.
Only tested with tty; some interfaces handle location themselves and
may need their own fixup for this.
Fixes#1046
Adds a more general way to handle gameplay tips, and adds
a boolean option "tips", which can be used to disable all
tips. Adds a helpful longer message when the game goes
into the "farlook" mode.
Also adds a lua binding to easily show multi-line text
in a menu window.
Breaks save compat.
Add "walls of lava", basically lava which blocks vision and
require a bit more than just levitation or flight to move through.
No levels use this yet, as testing isn't thorough enough.