There was a transcription error in the comments in cstd.h for
the standard list of header files, where only the description
remained for <stdlib.h>, not the name of the file itself.
Remove several extraneous inclusions of the standard C99 headers.
Tested on the following afterwards:
Linux (using hints/linux.370) including tty, curses, qt6, and X11
macOS (using hints/macOS.370) including tty, curses, qt5, and X11
Windows MSYS2 using sys/windows/GNUmakefile
Windows Visual Studio using sys/windows/Makefile.nmake
msdos cross-compile on Ubuntu using djgpp cross-compiler
GitHub issue #1315 points out that it is possible for
a downstream function to change an object's nobj field
to point to a completely different chain.
The cited example by @vultur-cadens was:
for (obj = gi.invent; obj; obj = obj->nobj)
if (obj->oclass != COIN_CLASS && !obj->cursed && !rn2(5)) {
curse(obj);
++buc_changed;
}
curse() drops the weapon with drop_uswapwep(),
which calls dropx(),
which calls dropy(),
which calls dropz(),
which calls place_object().
place_object alters the nobj pointer, to point to the floor chain:
otmp->nobj = fobj;
fobj = otmp;
The result was that the next loop iteration was then using floor
objects from the floor chain.
This alters several for-loops to use a more consistent approach,
particularly when the obj is being handed off to a function,
where a downstream function might, or might not, alter the nobj
field.
References:
https://github.com/NetHack/NetHack/issues/1315https://www.reddit.com/r/nethack/comments/1gkc9ub/even_if_you_drop_an_item_before_drinking_from_the/
Changes to setuhpmax() a couple of days ago to deal with sanity_check
for "current hero health as monster better than maximum" ended up
triggering sanity_check about "current hero health better than maximum"
when gaining experience level(s) while polymorphed.
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 old nowrap_add() had different semantics from its replacement,
performing an assignment as well as an addition. Now just does
the addition; its caller needs to perform the assignment.
Yahoo!'s mailer delivered the report about nowrap_add() to my spam
folder, apparently because it thinks that the signature attachments
"may contain harmful content". :-(
nowrap_add() checks for signed overflow after the fact, so after
undefined behavior if that happens.
This rewrites nowrap_add() and moves it from end.c to integer.h.
I haven't generated any values big enough to exercise it, but the
algorithm is straightforward so I'll take it on faith.
Even 100 deaths wasn't enough, as the fuzzer was still quitting.
If we're in wizmode, just execute wizmakemap to recreate the level,
getting rid of whatever was blocking hero from teleporting to safety.
new .h files: hacklib.h selvar.h stairs.h
new .c files: calendar.c, getpos.c, report.c, selvar.c, stairs.c,
strutil.c, wizcmds.c
cleanup of hacklib.c and mdlib.c
hacklib contains functions that do not have to link with the core
relocate wiz commands from cmd.c to wizcmds.c
relocate CRASHREPORT stuff to report.c
relocate getpos stuff from do_name.c to getpos.c
remove temporary struct definition from extern.h
cross-compile PRE-section split into cross-pre1.370 and cross-pre2.370
Windows sys/windows/Makefile.nmake and sys/windows/Makefile.mingw32 and
visual studio project file updates
Unix sys/unix/Makefile.src, sys/unix/Makefile.utl
populate selvar.c and selvar.h
build on MS-DOS (not cross-compile) Makefile updates
for sys/msdos/Makefile.GCC (untested)
vms updates for above (untested)
Replace tabs, split 'if (condtion) do_something' across two lines,
insert lots of spaces in things like 'if(condition){'. I changed
a lot of C++ style comments to traditional C style, but left quite
a few of those as-is.
This also rewrites the code that pull request #1216 purports to fix.
I still can't make sense of the original and the patched edition.
Supersedes #1216Closes#1216
DUMPLOG requests the DUMPLOG feature as it does now
DUMPLOG_CORE requests the internal buffering only (used for CRASHREPORT)
This allows CRASHREPORT to access recent messages without performing
any file I/O.
end.c:177:16: warning: unused parameter 'why' [-Wunused-parameter]
177 | NH_abort(char *why)
| ~~~~~~^~~
end.c: At top level:
end.c:1191:1: warning: 'get_saved_pline' defined but not used [-Wunused-function]
1191 | get_saved_pline(int lineno){
| ^~~~~~~~~~~~~~~
options.c:1263:1: warning: 'optfn_crash_urlmax' defined but not used [-Wunused-function]
1263 | optfn_crash_urlmax(int optidx UNUSED, int req, boolean negated UNUSED, char *opts, char *op)
| ^~~~~~~~~~~~~~~~~~
options.c:1240:1: warning: 'optfn_crash_name' defined but not used [-Wunused-function]
1240 | optfn_crash_name(int optidx UNUSED, int req, boolean negated UNUSED, char *opts, char *op)
| ^~~~~~~~~~~~~~~~
options.c:1217:1: warning: 'optfn_crash_email' defined but not used [-Wunused-function]
1217 | optfn_crash_email(int optidx UNUSED, int req, boolean negated UNUSED, char *opts, char *op)
| ^~~~~~~~~~~~~~~~~
add CRASHREPORT for Windows
add ^P info to report (via DUMPLOG)
new options: crash_email, crash_name, crash_urlmax
new game command: #bugreport
new config option: CRASHREPORT_EXEC_NOSTDERR
new command line option: --bidshow
deleted helper scripts:
NetHackCrashReport.Javascript
nhcrashreport.lua
misc:
update CRASHREPORTURL (will need to be updated before release)
update bitrot in winchain
winchain for Windows
add missing synch_wait for NetHackW --showpaths
add PANICTRACE (and CRASHREPORT) in mdlib.c:build_opts
missing:
packaging (Windows needs the pdb file)
no testing with MSVC command line build
port status:
linux: working, but glibc's backtrace doesn't show static functions
Windows VS: working. pdb file is large - looking into options
MacOS: working
msdos: not supported
VMS: not supported
MSVC: planned, but not attempted
MSYS2: working, but libbacktrace not showing symbols (yet?)
Some functions are passed an obj or monst chain,
and the callers typically don't check them
against 0, so mark them explicitly as NO_NONNULLS
(NO_NONNULLS expands to nothing, but it flags that
some null arg analysis has been done)
Thinko in the reformatting, not triggered during testing because I was
using !CRASHREPORT. With it enabled, setting a watchpoint in gdb on
something unrelated resulted in nethack going into crashreport_init()
and never caming out. (I imagine that it would have eventually but 10
or 15 minutes with nothing noticeable taking place was unbearable, and
the program hadn't even really started yet.)
Fixup some of the inconsistently formatted code that has been
introduced recently or been building up for a while. Done manually.
I wasn't systematic except for looking for lines ending in '&' or '|'
(which wouldn't find such things if they're followed by a comment)
so there might be lots more. I changed a bunch of C++-style //...
comments to old style C /*...*/ so that they'll match the rest of
the core's code rather than because they shouldn't be used.
As part of the tty resize handling revision, code dealing with the
perm_invent window was moved out of tty_destroy_nhwindow() was moved
into a separate routine. The new routine would have been called for
a window of NHW_PERMINVENT, but WIN_INVENT doesn't have that type,
just ordinary NHW_MENU, so the cleanup wasn't happening, resulting in
a memory leak.
Simplify suppression of highlighting for menu header lines during end
of game disclosure. Didn't actually affect as many things as I was
expecting.
Plus a bit left out of the optfn_dogname() parsing commit.
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
Reported by entrez, some putstr() to text window got changed to
add_menu_str(). I didn't test with curses; with tty some headers
ended up in limbo: "Artifacts" header for '` a y' (wizard mode show
artifacts, something I had forgotten even existed) and also monster
class headers for 'm #vanquished by-class' (available to everyone).
Qt lost them too, but at least it didn't panic.
Not due to over-simplification: end of game disclosure suppresses
header line highlighting, except when disclosing final inventory.
Change it to do so, although it would be simpler overall to just not
bother with any menu_headings highlight suppression.
When the hero is killed by a zombie, she is supposed to arise from the
grave as a zombie of a type matching her race. Commit 580c5a6 broke
this inadvertently -- done_in_by was passing gy.youmonst.data to
zombie_form() and relying on the old behavior where it attempted to
include the hero's race in is_elf, is_orc, etc if the permonst matched
the hero's role. Because this no longer works, zombie_form was only
returning PM_HUMAN_ZOMBIE when passed the role permonst of an
unpolymorphed hero. Use gu.urace.zombienum instead. This would have to
be a little more sophisticated (falling back to zombie_form() if Upolyd)
if a polymorphed hero with unchanging could die via done_in_by but
that's not currently possible as far as I can tell.