When you were asked for a name and teleported out of the vault without
any gold on you, the vault guard says "Well, begone" - which could be
heard from anywhere on the level.
Limit that verbalization to 10 tiles away.
Move the caitiff check into thitmonst, the code responsible
for object hitting a monster, intead of checking the caitiff
in multiple places before calling that.
Previously there were some cases where caitiff was not checked,
eg. samurai could fire arrows at a peaceful monster without
the dishonourable behaviour check.
Now you will get the check even if you miss with the projectile.
This may need to be adjusted for throwing beneficial potions
at monsters...
This is a follow-up to commit 9114a33 that was intended to fix a "killed by a died" situation.
In that commit, the generic case could be encountered with variable str set to "explosion",
but that never got copied to svk.killer.name, and svk.killer.name remained set to "died"
during testing.
svk.killer.format = KILLED_BY_AN; is done whether the generic case, or not.
Close#1676
"This plugs into the same code that provides support for BMP and GIF tiles for MS-DOS, and also populates the stub to read PNG tiles.
PNG is a compile-time option, and depends on libpng."
pull request #1666 by chasonr
It is difficult, but possible, to exceed 1024 widgets. One way is to
set a very large Unicode symbol set, and then use #wizcustom. As there
is no limit to how many objects can occupy a square, this limit is a
possible hazard even to a normal game.
In 3.6.x, zombie corpses were always aged an extra 100:
NetHack/src/mon.c
Line 375 in 23d331a
obj->age -= 100; /* this is an *OLD* corpse */
in 5.0.x, zombie corpses are always aged TAINT_AGE, which is only 50:
NetHack/src/mon.c
Line 648 in 97a6c13
obj->age -= (TAINT_AGE + 1); /* this is an *OLD* corpse */
This is the result of commit 408321b.
The accompanying comment states that the purpose of that patch was meant to
just replace hard-coded numbers with symbolic values, but the commit set
two differing numeric values to the same symbol name, thus causing the
regression reported in:
https://github.com/NetHack/NetHack/issues/1664
Revert the values to match those of 3.6, and add the additional symbolic value.
Closes#1664
Fix#576
Reported initially by @copperwater for polymorphed monsters:
"observe how the [polymorphed-monster] hovers placidly above the water for
several turns like Wile E. Coyote before it gets a move, realizes it's
above water, and drowns. Ditto for lava."
A comment in the GitHub issue thread by @Tomsod pointed out that a
revived corpse could do the same.
This should set things up for other terrain fallout if discovered or
implemented in the future.
- consume an additional bit in enum mon_terrain_effects (hack.h)
- include the additional bit in TERRAIN_FALLOUT_MASK (monst.h)
- add detection to maybe_set_terrain_effects (mon.c)
- add action to terrain_effects (mon.c)
Implemented by stealing some upper unused mstate bits to avoid
invalidating existing save and bones.
If a line in the menu has fewer columns than the others, the last one
is deemed to extend to the right margin, and does not count toward the
maximum width of that column.
Also, revert the change to NetHack.font_menu.
../sys/unix/unixmain.c: In function ‘process_options’:
../sys/unix/unixmain.c:458:9: warning: use of uninitialized value ‘origarg’ [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
458 | config_error_add("Unknown option: %.60s", origarg);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Set the menu font to proportional
* Do not consider the last column of a line when calculating maximum
column widths
* Use U+200A HAIR SPACE for finer column padding
* Track errors in column padding and adjust subsequent columns so that
these errors do not accumulate across a row
../src/pline.c: In function 'execplinehandler':
../src/pline.c:678:15: error: implicit declaration of function '_spawnv' [-Wimplicit-function-declaration]
678 | ret = _spawnv(_P_NOWAIT, sysopt.msghandler, args);
| ^~~~~~~
../src/pline.c:678:23: error: '_P_NOWAIT' undeclared (first use in this function); did you mean 'MM_NOWAIT'?
678 | ret = _spawnv(_P_NOWAIT, sysopt.msghandler, args);
| ^~~~~~~~~
| MM_NOWAIT
../src/pline.c:678:23: note: each undeclared identifier is reported only once for each function it appears in
make: *** [GNUmakefile:1376: o/nethack/pline.o] Error 1
The widget is created with a label but not a pixmap, and then a pixmap
is set up for display. If the label is already realized and managed, it
will not resize when the pixmap is set up. This causes problems when
the inventory window is updated: unlike other menus, the parent Form
widget is already realized. The fix is to create the item widget in an
unmanaged state (XtCreateWidget), set up the pixmap (X11_wrap_widget
and X11_set_attrs), and then manage it (XtManageChild).
Unix command line handling treated an unknown command line parameter
as a maximum number of allowed concurrent players. This emitted
a complaint about expected MAXPLAYERS, and as it can be now set
in sysconf, remove this - most likely unused - functionality.
early_init() was already being called at pcmain.c line 70,
so the recently added call at line 132 was problematic
because it cleared program_state values that had been
intentionally set since the call at line 70.
save_currentstate() increments program_state.in_checkpoint and then
returns early without decrementing it when currentlevel_rewrite()
fails (full disk, quota, unwritable directory). The guard at the top
of the function suppresses every later checkpoint for the rest of the
game, leaving recover with nothing newer than the last checkpoint that
did get written, and nothing says so.
savestateinlock() returns early unless
program_state.something_worth_saving is set, but both call sites that
are meant to lay down the initial checkpoint run before that flag is
set: newgame() calls save_currentstate() two lines early, and
dorecover() calls savestateinlock() 73 lines before it, ahead of the
pass that writes out the level files.
Both calls are therefore no-ops, and the <uid><plname>.0 lock file
holds nothing but the pid written by getlock() until the hero first
changes dungeon level. A game that dies without a chance to save
during that window (SIGKILL, OOM killer, watchdog, host reboot)
cannot be rebuilt: recover has no save file name, no current level
number and no game state, and reports "Checkpointing was not in
effect", which is true of the outcome but misleading about the cause.
The window covers the whole of a long stay on one level, and in
particular the entire period right after a restore.
Set the flag before the call in newgame(). In dorecover(), drop the
ineffective call and checkpoint once the restore is complete instead;
at the original spot no level file for this session has been written
yet, so a checkpoint there would name a current level and save file
that are not on disk. The new call goes after program_state.restoring
is cleared, so that stairs and traps are written with the same
relative dlevel encoding a normal save uses, and it is
save_currentstate() rather than savestateinlock() so that
in_checkpoint is set while savegamestate() writes u.ustuck_mid and
u.usteed_mid.
This arrived with the something_worth_saving guard; 3.4.3, which has
no guard, is unaffected. Looks like this issue has been around since
version 3.6.0.
Reported directly to devteam, the code was using "Your little dog
devours the tripe ration" during the taming process, prior to the
pet becoming yours.
The startup had fallen behind NetHack 5.0 startup for other platforms,
and lacked support for some of the early command line options.
Following this, if PC_EARLY_OPTIONS is defined in pcconf.h, the
port will support those options, such as --version, --showpaths,
--dumpenums, etc.)
Currently, MSDOS #defines's PC_EARLY_OPTIONS, but AMIGA, ATARI,
and MAC68K do not.
If there are, say, two or more potions in the menu, and multiple
selections are allowed, then '!' should select all potions. Such keys
were selecting only the first matching item.
Renders to a Pixmap and then sets the Pixmap. This in itself does not
change the appearance, but provides a means to do percentage bars,
italics and more.
This was trying to retrieve the foreground color of the form created
in create_value(). Forms don't have colors, and so this was failing,
and update_color() didn't update the color.
Menu windows with lots of entries (such as #optionsfull) were taller
than the screen, making them awkward to use.
The widget needs to be realized before we can get the size.
Also, we need to set the size of the parent popup, not the
acting widget.
This is intended to resolve GitHub Issue #1650, which I was unable to directly reproduce
on my test system.
This fix assumes that the reported issue was related to cmdstr[BUFSZ] buffer not
getting initialized, thus containing random memory values.
1d3178a quieted the g++ build, but made the warnings even
worse with a clang build.
The addition of the -Wno-sfinae-incomplete caused an unrecognized
option warning using recent clang.
Recent clang build with Qt6.1 also caused several warnings
during the processing of the Qt6.1 header files related to
c++26-extensions.
This adds (under Linux) -Wnoc++-26-extensions to the clang++
command line to quiet those warnings and restricts the
-Wno-sfinae-incomplete command line option to the g++ build.
In the event that there is a collision between a menu group accelerator
and an individual menu item's accelerator, disregard the group
accelerator.
'$' is the only known collision in NetHack 5.0 presently.
Close#805
Reported by @youbo0 in GitHub issue #1616
This issue text stated:
"To enter wizard mode, I have a shortcut with -D -u wizard as suggested by
the wiki for Windows players. However, the name is now overridden by a name
in .nethackrc since 5.0, resulting in me not actually entering wizard mode
due to having the wrong name despite using -u wizard. In the previous
version, -u wizard was applying properly regardless."
Closes#1616
This is an initial attempt at adding support for hilite_pet and
hilite_pile to the msdos tile implementation, using the new
decal.txt tiles.
This initial attempt only supports a 16-bit vesa mode.
Other vesa modes and vga have not been done as of yet.
Hopefully, someone more familiar with vesa might contribute
improvements and support of the other modes at some point.
win/share/decals.txt contains (initially) a decal_delimiter tile,
a decal_pet tile, and a decal_pile tile.
The latter two can be used for hilite_pet and hilite_pile implementations
that don't have something in place already. The implementation would
just need to apply (merge) the non-background decal pixels over a
regular tile.
The special decal_delimiter tile can be used to confirm the presence
of the delimiter tiles in the tileset and mark the end of the regular tiles,
and the start of the decal tiles.
row 1 contains the background color whose pixels should be
ignored when applying a decal to a tile.
row 2 contains a row of pixels colored (0, 0, 0).
row 3 contains a row of pixels colored pure green (0, 255, 0).
row 3 contains a row of pixels colored pure blue (0, 0, 255).
cmd.c: In function ‘dokeylist’:
cmd.c:2961:23: warning: ‘]’ directive writing 1 byte into a region of size between 0 and 255 [-Wformat-overflow=]
2961 | Sprintf(buf2, "[%s]", key2txt(key, buf));
| ^
Enable USE_BUFFERING for the structlevel savefile write path on AMIGA
and TOS via a new SFSTRUCT_BUFFERING config define, with a 16 KB
setvbuf on the fdopen'd write stream so many small bwrite()s coalesce
into few dos.library Write() packets. Leaves mread() unbuffered.
Mainline UNIX/WIN32 are unchanged (setvbuf is gated on the new define);
MAC68K is not enabled, avoiding fdopen()/fclose() on its remapped
non-libc file handles.
Use LUA_VERSION_NUM, not LUA_VERSION_RELEASE_NUM, for the check.
Move the definitions of the versions supported by this release of
NetHack to the top of nhlua.c, rather than 2300 lines into the file.
Close#1633
In previous versions of NetHack, setting -DUSE_TILES enabled the tile
support, while setting -DSUPPRESS_GRAPHICS produced a NetHack that
would write its TTY output to standard output, and rely on ANSI.SYS or
similar to do screen control. (USE_TILES is now TILES_IN_GLYPHMAP.)
This change ensures that the current NetHack can be built the same
ways.
One twist is that previous NetHacks would drop all support for graphical
modes when tiles were not supported. Thus sys/msdos/vid{vga,vesa}.c have
very disordered use of TILES_IN_GLYPHMAP. There was no need to check
this. But now, the graphical modes also support Unicode. A non-tiled
build should have the graphical modes, with only the text functions
present, provided that ENHANCED_SYMBOLS is defined.
Some unused and locally used symbols were cleaned up along the way.
In 16 color mode, text colors are mapped onto the colors available in
the tileset. The mapping is a compromise, and is not one-to-one: cyan
and bright cyan are the same, and magenta and bright magenta are the
same.
This change defines a separate palette for use by the text map, and
switches palettes on any transition between text and tiled maps.
During a synchronous save operation initiated by the player (or
other trigger for dosave0()), the u.usteed_mid and u.ustuck_mid
values get set by savemonch(), and the monst pointers that
u.ustuck and u.usteed point to are no longer valid, but not
cleared.
The checkpoint operation, which also needs to ensure that
u.ustuck_mid and u.usteed_mid are set, must set them during
the checkpoint, which is okay because the u.usteed and
u.ustuck pointers _are_ valid during a checkpoint operation.
So, we need to distinguish between a save game sequence,
and a checkpoint sequence when writing out the u struct.
* In both the 16 color and the VESA mode, the tileset image is loaded
and split into individual tiles; the tiles are then processed into a
form that is compatible with the video mode in use. For 16 color mode,
a tile is processed each time it is displayed, leading to slow
redrawing. For VESA mode, each tile is processed at startup, leading
to long startup times. Both modes are changed so that the tile is
processed once, when it is first displayed, and the result is cached.
* Use memcpy when splitting the image into tiles.
* Only load the tileset once. In 16 color mode, for reasons I do not
understand, the gr_init function is called twice, leading to delay
in startup. This does not happen in VESA mode.
* src/glyphs.c: Don't produce names for swallow glyphs that can never
appear. This speeds up the building of the glyph index in
populate_glyphname_hash_indices.
* src/symbols.c: Build a sorted index for loadsyms so that it can be
searched with bsearch.
Benchmarking results, using the MS-DOS port on an emulated 386SX at
16 MHz; times are as measured with clock() from the entry to main()
to the appearance of the "Who are you?" prompt:
* Unmodified: 48.5 seconds
* With the loadsyms index: 40.4 seconds
* With impossible swallow glyphs left unnamed: 34.5 seconds
These changes should also be helpful for the Amiga and Atari ST ports.
The 16 color mode loads the font specified in font_map, and accepts it
only if its size is 8 by 16 pixels. This change avoids a null
dereference if the font is not found.
This change adds U+2299, U+2601 and U+2980 to the bundled fonts, so
that all symbols specified in the Extended2 symbol set are available.
Also, a few more directives are added to the files, so that FontForge
can load them and display their contents.
When corpses haven't stacked, and there is no player-discernable
reason why, provide some additional information in some cases,
but only when it is required.
Gender variance is the supported case in this commit.
Related to GitHub issue #1607.
This commit doesn't change the underlying mechanics to allow
the corpses to stack, but it does help the player understand
why that's the case in this instance.
In file included from ../include/hack.h:34,
from sp_lev.c:14:
In function ‘create_monster’,
inlined from ‘lspo_monster’ at sp_lev.c:3386:5:
../include/rm.h:528:32: warning: array subscript -1 is below array bounds of ‘struct monst *[80][21]’ [-Warray-bounds=]
528 | if (!svl.level.monsters[x][y]) \
| ~~~~~~~~~~~~~~~~~~^~~
sp_lev.c:2045:25: note: in expansion of macro ‘remove_monster’
2045 | remove_monster(x, y);
| ^~~~~~~~~~~~~~
../include/rm.h: In function ‘lspo_monster’:
../include/rm.h:476:19: note: while referencing ‘monsters’
476 | struct monst *monsters[COLNO][ROWNO];
| ^~~~~~~~
In function ‘create_monster’,
inlined from ‘lspo_monster’ at sp_lev.c:3386:5:
../include/rm.h:530:27: warning: array subscript -1 is below array bounds of ‘struct monst *[80][21]’ [-Warray-bounds=]
530 | svl.level.monsters[x][y] = (struct monst *) 0; \
| ~~~~~~~~~~~~~~~~~~^~~
sp_lev.c:2045:25: note: in expansion of macro ‘remove_monster’
2045 | remove_monster(x, y);
| ^~~~~~~~~~~~~~
../include/rm.h: In function ‘lspo_monster’:
../include/rm.h:476:19: note: while referencing ‘monsters’
476 | struct monst *monsters[COLNO][ROWNO];
| ^~~~~~~~
This is a reimplementation of commit ec32748 in TNNT by entrez:
If you use undead turning on a dead hero's corpse from a bones file,
its ghost will get sucked back into its body when it comes back to
life. In such cases, treat the newly revived corpse/recorporealized
ghost as a "former hero" for the purposes of livelogging bones
monster kills.
Part of this change was to remove a bit of weirdness in the game - the
odd situation where you revive a corpse-ghost combo on a bones pile, and
get the messages:
The human corpse glows iridescently.
Foo's ghost is suddenly drawn into its former body!
The human is resurrected!
and subsequently the monster is just a generic human (or elf, etc)
without anything indicating it used to be a player. With this change,
the monster will retain the name that the ghost had, and its struct
ebones prevents the player from renaming it.
This commit also adjusts the "resurrected" message to explicitly use the
monster's name if it has one, and to use YMonnam in the unrelated case
where the monster was a pet (so reviving an unnamed tame kitten will
print as "Your kitten is resurrected!")
Keep only 8 background colours but if curses supports 256 colours and
256*8 colours pairs, create colours pairs for 256 foregrounds rather
than just 16.
It will need another parameter for 256-colour support. To avoid having
too many arguments, put glyph colour, background colour and attributes
into a struct and, since to curses library all of that is attributes
that are handled by same function, call the struct "gryph attributes".
curses_putch was also declared in two different headers, remove one of
those declarations.
The blue background colour for piles was implemented by changing glyph
colour to curses colour pair with the desired background, and then
passed to curses_putch which takes character and background colour and
makes curses colour pair out of them once again.
Pass blue background to curses_putch instead and let it create curses
colour pair just once.
This is an issue that we discovered in TNNT last year when we added a
custom region with effects that trigger upon entry: it was possible to
bypass those effects by entering the region via a thrown iron ball.
This can be demonstrated by creating a poison gas cloud and then
dragging oneself inside the cloud behind a thrown ball: you land in the
cloud and are surrounded by poisonous gas, but are unharmed by it.
This commit fixes the iron ball code to call in_out_region when
appropriate, which handles the side effects of entering and exiting
regions in addition to preventing travel into or out of a hypothetical
region that blocks entry or exit.
The message in question is '[shopkeeper] says "You be careful with my
[item]!"' when you wield a shop-owned item, but it was being printed
even when the hero is deaf.
Following other examples of shopkeeper dialogue, the correct thing to do
here is not to suppress the message if deaf but instead provide some
nonverbal feedback, so that is what I did.
see_monsters() was producing spurious vault guard at 0,0
messages
Reproduce issue by:
1. Entering vault via teleport.
2. Wait for guard to enter.
3. Drop gold (if necessary) and follow guard.
4. Right after the guard disappears, but before
the corridor does, the following can lead to
the messages:
a) control-R to refresh the display.
or
b) save the game and restore.
In both cases, see_monsters() will get called and lead
to the spurious messages for the vault guard that is
parked.
Also, add a macro PARKEDMONSTER(mon) instead of checking the
the isgd bit and the value of mon->mx being zero in multiple
places
Also, adds MON_PARKED bit to mstate.
Currently the PARKEDMONSTER(mon) macro mentioned above,
does not use the new bit.
* makefont.lua generates incorrect PSF fonts. There can be multiple
characters mapped to a single glyph, but the mappings should be
separated by FE bytes.
* font.c should accept only single character mappings -- not combining
sequences. The bundled fonts have no combining sequences, but I am
exploring other options that provide more Unicode coverate.
The old logic used a negative check to emit an extern declaration for
tparm(). This guarded against old platforms whose curses implementations
did not declare their own functions.
If there are still any platforms left that need this declaration, they
can set TPARM_WORKAROUND to get the old behavior back.
VESA mode: Set the viewport size correctly so the position bar does
not overlay the map.
VESA mode: Correctly set the size to which tiles are stretched when
overview mode (F4) is selected.
Both VESA and 16 color modes: Pass correct parameters to vga_userpan
and vesa_userpan, so the pan keys (CTRL+arrow) work correctly.
Some emulations don't report CTRL with up or down arrows, so accept
CTRL-home, CTRL-page up, CTRL page down and CTRL-end.
16 color mode: Set the panning direction so CTRL-left and CTRL-right
pan in the same direction as 3.4.3.
Pull request from youbo0: when hero's alignment gets low enough, the
adjusted experience level for erinyes effetively dropped instead of
increased. It was being capped at 50 which has a special meaning for
monsters.
Change the level limit to 49 which is as high as ordinary monsters go.
Does not affect saved data.
Fixes#1557
They aren't initially loaded with boulders, thus aren't dangerous.
This is particularly relevant for pets, who would otherwise be very
reluctant to follow their owners up to the level above.
If a monster is marked as off the map, then it is included in
iterations over the monster list, but not allowed to move. This
meant that such monsters would gain movement points on every turn
but not spend them, which could lead to the monster taking a lot of
turns in a row when placed back onto the map.
This commit removes the movement allocation from monsters that are
flagged as dead or removed from the map, meaning that they neve
get more than one turn's worth of movement allocation.
The basic colors are being displayed as black. Colors specified as RGB
are not being converted to the pixel format for the current mode. This
manifests as walls in dungeon branches being drawn in black when the
symbol set is IBMgraphics, and in the wrong color when Enhanced1 is in
use and the display mode uses 15 or 16 bits per pixel. A particular
mode that shows this bug is 1024 by 768 under DOSBox.
u.ustuck and u.usteed are handled differently in 5.0.0 than
in previous releases, and an unexpected halt to NetHack could
result in an inability to use recover to get the game back.
If the hero was engulfed, u.uswallow, could get saved to the
checkpoint file with a value of 1 without a corresponding
u.ustuck_mid value representing the m_id of the engulfing monster.
Recover had no information to use to restore the u.ustuck pointer
when loading the monsters on the level.
With u.uswallow set to 1, the game would proceed to enter if-blocks
based on that, and then crash/fault when it attempted to dereference
u.ustuck, during the recover attempt.
This updates the values of u.ustuck_mid immediately before saving
struct you during a checkpoint, so that the resulting file had
u.uswallow and u.ustuck_mid values that were in concert.
It does the same for u.usteed and u.usteed_mid.
This also now adds a save_currentstate() checkpoint call when
the swallowed/unswallowed status changes, that is whenever set_ustuck()
is called.
The revived mac68k port (on the m68k-wip branch) removed it: it runs
an event loop after exit_nhwindows() has torn the windowing system
down and crashes; the tombstone already pauses. Removing it here too
keeps the block from resurfacing in NetHack-5.0 <-> m68k-wip merges.
track which locations had updates that could be seen in tmp_at()
to aid in cleanup.
ensure that nothing is shown for places that the hero can't see
(internal buglist entry 3161).
adjust several aklys messages to better reflect the tethering
aspect.
LUAMAKEFLAGS uses TARGET_CC, which the cross hints override to the
target compiler. The top-level liblua.a is a host-side prerequisite
of the generated include/nhlua.h; the target lua is built separately
under BUILD_TARGET_LUA.
A very small number of boolean options had drifted, such that
their initval setting did not match its opt_in or opt_out value.
Correct that, by ensuring opt_in or opt_out reflects what was
actually happening.
The only option whose initial value is changing as a result
of this is timed_delay. It was listed as an opt_out option, but
was not being initialized as such. Now it is. This makes the
Mac X11 throwing animations work correctly with the earlier
timed_delay option adjustments for X11. There was nothing
displaying on Mac X11 after those earlier changes, unless
the timed_delay option was turned on.
Going forward, for boolean options, setting opt_in or opt_out
is all that is required, as that was the original intention
of those fields. It will take precedence if they fall out of
sync again.
I noticed a strange thing where the X11 windowport didn't show the tethered
thrown aklys animation correctly. Interestingly, other stuff, such as zapped
wands did show the path. I didn't bother trying to figure out what the core
was doing differently, as the animation worked in all the other windowports,
so instead fix the issue in X11, so it behaves the same as all the others.
The issue seems to be that the event loop exited on any(?) event, instead
of our specific timed event. So, create our event with a magic id number,
and exit only when we encounter that.
Also: Obey the timed_delay option, and change the delay from 30ms to 50ms,
like in other windowports.
This is better placement for making the original
engraving vanish when told that it vanishes;
helps to ensure that it isn't showing for any
next steps.
also, a warning bit
During a restore from a savefiles is not the only
time that levels are processed by getlev() in NetHack.
They are read back in as the hero moves up and down
between levels and dungeons.
The previous fix checked for program_state.beyond_savefile_load,
but once set, that remains static through level changes.
It would be better to check the status of the level
being read, because those operations do placements as well.
Add the following:
struct levelstatus level_status;
level_status.making - in the midst of makelevel processing
level_status.loading - in the midst of loading a level via getlev()
level_status.ready - the level is fully ready
(all 3 of the above status settings are mutually exclusive)
level_status.shkready - the level processing is far enough
along to allow shop keeper tests and actions
This also relocates the find_lev_obj() call in getlev() down several
lines, so that it falls after any set_residency() calls, so that it
has a better chance of carrying out what it was intending to do with
the shop_keeper() checks made by its subfunctions.
In SELECTSAVE implementations, out of date savefiles in the
tree were triggering error messages to the user during the
building of the pick list. The file with the error never
ended up on the pick list, or got removed, so the error was
perpetual on every SELECTSAVE startup.
This passes the UTD_QUIETLY flag down the the small set of
callers involved, so that when it was received by uptodate(),
it went about its verification work quietly.
The terminfo entries from the standard ncurses distribution have
peculiar settings for entries supporting 24 bit colors. The direct
entries mix indexed and RGB values into an incompatible mess.
This commit adds a simple workaround for the tty port. Colors are
initialised as if only 8 ANSI colors are available. This does not
affect color customisation from the symsets.
The curses port is affected as well. But I am not yet comfortable to
refactor a large part of the code for an absolute edge case.
- cmap_offset was calculated on every compose_glyph_name() call;
calculate it once with a static function.
- Drop parse_id's G_ auto-populate: an unbracketed lookup allocated
the index with no matching free. Linear-scan instead when absent.
- compose_glyph_name: require bufsz >= BUFSZ, build names with
bounded Snprintf instead of Strcpy/Strcat, drop the dead memchr.
- parse_id's permonst scan used i <= pm_count, reading one past the
SYM_MON block (S_nothing) and matching it as a monster; use <.
- Drop a stale NO_GLYPH empty-bucket comment from the open-addressed
table.
The directories and permissions portion of the linux.500 and macOS.500
hints files and their included files has been consolidated to
dirs-perms.500.
The builder can edit that one file now, to identify
the folders that will be utilised as part of the build.
Alternatively, you can set those folders and permissions in a
make.perms file in the top of the NetHack folder tree and
they should take precedence over the ones in dirs-perms.500
because dirs-perms.500 uses '?=' variable assignment, which
means "set the value of the variable if no value has been set."
* NOTE: BUILD CHANGE *
This also makes WANT_SOURCE_INSTALL=1 the default over
WANT_SHARED_INSTALL=1, if neither is explicitly set.
The new default is the safer and less-impacting default,
but it will change where things get installed over earlier
Makefile builds. You can be explicit with WANT_SHARED_INSTALL=1
in your make command to get that..
These are the differences between the two:
make WANT_SHARED_INSTALL=1 Place the results of the install/update portion
of the build into a shared area on a multiuser
system.
make WANT_SOURCE_INSTALL=1 Place the results of the install/update portion
of the build into a subfolder of the source
tree, rather than in a system-wide shared area.
Also note that the macOS hints file behaves slightly differntly depending
on whether WANT_SOURCE_INSTALL=1 was set versus letting it be the default.
That's not new, it behaved that way before.
Be able to carry out uplifts during minor release
lifetimes.
Document a way to be able to uplift struct content
without incrementing EDITLEVEL and breaking existing savefiles.
Use the mechanics outlined to uplift the contents instead, where
it is feasible to do so. The uplift is currently one-way only. An
uplifted savefile cannot be used with an earlier build of NetHack
, one built with a lower SAVEFILE_REVISION_LEVEL, than the one which
wrote the savefile.
The final byte (byte 79) of the 80 critical bytes in the savefile,
of which 10 are reserved for future expansion and not currently
used, will now be used for holding the savefile revision level
(SAVEFILE_REVISION_LEVEL in include/patchlevel.h) at the time
the savefile was written.
That leaves 9 of the bytes available for future use.
The previous rotate-1-xor put consecutive characters' bits in
adjacent positions, so short similar names like fox/bat or
jaguar/lichen collided -- 164 colliding buckets across the 9577
named glyphs. Rotate-5 spreads each character across a 5-bit
window: zero true collisions, one m68k ROL.L, no multiplication.
The 16 remaining same-hash buckets are name duplicates from a
separate compose_glyph_name bug, addressed by its own fix.
parse_id's glyph_is_object branch only emitted the "piletop_" prefix
when glyph_is_normal_piletop_obj(glyph) was true. Piletop-generic
objects (the GLYPH_OBJ_PILETOP_OFF + 1 .. + LAST_GENERIC range) hit
glyph_is_piletop_generic_obj() instead and got no prefix, so they
produced the same canonical name as their non-piletop generic
counterparts.
For example glyph 3449 (GLYPH_OBJ_OFF + GENERIC_STRANGE) and glyph
7993 (GLYPH_OBJ_PILETOP_OFF + GENERIC_STRANGE) both yielded
"G_generic_strange". 14 such pairs exist; the piletop variant is
unreachable by name from nethackrc, and the runtime hashtable's
"assume no id occurs twice" populate loop silently dropped them.
Emit "piletop_" for both piletop predicates so each glyph gets a
distinct canonical name. --dumpglyphnames now shows the 14
"G_piletop_generic_*" entries (and the count goes from 9577 to 9591;
the existing off-by-one in glyph_is_normal_piletop_obj still hides
slot GLYPH_OBJ_PILETOP_OFF + FIRST_OBJECT - 1, which is addressed by
its own fix).
The open-addressed glyphname_hashtable stored each canonical
"G_xxx" name as a dupstr'd string in its bucket: ~9577 small heap
allocations and ~290 KB of resident name strings, on top of ~256 KB
of 32768-bucket scaffolding kept at <50% load for probe performance.
On classic Mac OS the populate cost (quadratic small-allocation in a
fragmented Memory Manager heap) dominated startup time -- many
seconds on an SE/30 -- and ~800 KB resident is meaningful on the
small machines the port targets.
Switch to a sorted (hash, glyph) index sized exactly to the number
of named glyphs:
struct glyphname_hashtable_entry_t {
uint32 hash;
int glyphnum;
};
populate_glyphname_hashtable() allocates one block of MAX_GLYPH
entries (no per-name strings), fills it via compose_glyph_name() +
glyph_hash(), and qsort()s ascending by hash. Lookup binary-searches
the hash column, then walks any equal-hash neighbours verifying each
candidate by reconstructing its canonical name and strcmpi'ing it
back -- collisions are rare with 9577 uniformly-distributed 32-bit
hashes.
Other changes that fall out:
* Extract compose_glyph_name() from parse_id's bulk-iteration switch
so it is the single source of truth for "glyph number -> canonical
name". Called by find_glyph_in_hashtable for collision
verification, by populate_glyphname_hashtable, by the
--dumpglyphnames path, and by wizcustom_glyphnames.
* empty_glyphname_hashtable() reduces to free(ptr); no per-entry
strings to release.
* Drop find_glyphname_in_hashtable_by_glyphnum (no longer used --
wizcustom_glyphnames iterates compose_glyph_name directly).
* Drop the res_fill_hashtable parse_id mode; populate iterates
directly.
Memory drops from ~800 KB to ~75 KB. One allocation instead of
~9578. Lookup goes from O(1) to O(log N) but N ~ 9577 means ~14
comparisons per probe -- well under what the upstream cache ever
cost in practice.
Function names (populate_glyphname_hashtable, etc.) are kept for
extern.h compatibility; the data structure is now a sorted index,
"hashtable" in the names is historical.
--dumpglyphnames output is byte-identical.
glyph_is_normal_object includes its boundary slot
GLYPH_OBJ_OFF + FIRST_OBJECT - 1 via >=, but its piletop sibling
glyph_is_normal_piletop_obj used > and excluded the matching
GLYPH_OBJ_PILETOP_OFF + FIRST_OBJECT - 1 slot. That leaves
exactly one glyph (the would-be G_piletop_generic_venom) matching
neither the piletop-generic nor the piletop-normal predicate, so
parse_id never builds a name for it and --dumpglyphnames emits a
blank line for the slot.
Change > to >= so the two ranges are inclusive on the same side.
--dumpglyphnames now produces (8009) G_piletop_generic_venom.
Noticed this when testing a level with some barren trees which were set
in the special level to not contain bees; the barren trees are still
able to produce a low buzzing. This may convince players that they can
get bees from the tree if only they kick it enough times, which will not
happen.
To avoid that, only print this message when the tree can release bees,
augmenting the existing check for killer bees being non-extinct.
Two methods are now provided for slow ports/platforms that
need to do this for performance reasons.
Hopefully, this will avoid proliferation of more platform-specific
conditional code within initoptions_init().
Method (1): #define DISABLE_GLYPHID_CACHE_PREFILL in platform/OS's
include/*conf.h.
or
Method (2): set gd.disable_glyphid_cache_prefill = TRUE in startup code
after decl_global_init(), and prior to initoptions_init().
It has to be done after decl_global_init() because
decl_global_init() sets the value to its initialization
default.
- adjust the surface name in prompts (resolves a TODO in the code).
- be more player-friendly with the prompting, and don't prompt a
second time if the floor/surface is the only tip-destination, as
that can be annoyng and viewed as unnecessary. Instead, include
that information in the first decision prompt.
Resolves#1537
Add ANY_INT16 to any_types and use it for u.ux/uy/tx/ty and uz
dlevel/dnum. These are coordxy (int16_t) but the Lua bindings were
treating them as 1-byte fields, so on big-endian m68k Lua read the
high byte (0) instead of the actual value. Symptom: place_object
off map <0,0> in the tutorial.
Having a hard cap on the number of rerolls doesn't help save CPU
usage from excessive rerolling, because if the cap is set low
enough to keep the CPU usage reasonable it isn't high enough for
players to actually use the feature.
Instead, allow capping the number of rerolls per second. (Sensible
values seem to be in the 5-10 range.) If the player attempts more
rerolls than this, show a paranoid confirmation prompt: the need to
type the answer to the prompt will slow a human user down (and if
the prompt is filled in too quickly, it will simply just be shown
again, preventing attempts to use automation to skip the prompt).
menu_pick_pay_items() passed &nul_glyphinfo to add_menu so
port windowports never had a tile/glyph to render alongside
each entry on the bill. Compute the proper glyph_info from
the bill's obj, matching the pattern src/invent.c already
uses for inventory menus.
doloot_core(), choose_tip_container_menu(), and
tipcontainer_gettarget() each iterate carried or floor containers
and offer them as menu rows, but passed &nul_glyphinfo so port
windowports had nothing to render alongside. Compute proper
glyph_info from each container the same way src/invent.c
already does for inventory menus.
Tested:
Ubuntu: make WANT_WIN_TTY=1 WANT_WIN_CURSES=1 resp=1 update
Ubuntu: make WANT_SYSTEM_LUA=1 WANT_WIN_TTY=1 WANT_WIN_CURSES=1 resp=1 update
make CROSS_TO_MSDOS=1 package
make CROSS_TO_AMIGA=1 all
make CROSS_TO_AMIGA=1 package
Set things up so that the Makefile build will look for 'make.prefs'
at the top of the NetHack source tree.
If 'make.prefs' is present, the Makefile build will include it
just ahead of the PRE section of a hints file specified to
sys/unix/setup.sh, or practically the first thing during a
Makefile build if no hints file was specified.
The advantage of using a 'make.prefs' is that instead of putting a
series of Makefile variable value assignments on the command line
each time, like this:
make WANT_WIN_X11=1 WANT_WIN_TTY=1 WANT_WIN_CURSES=1 c2x=1 resp=1 update
you can, instead, put those preferences into make.prefs, like this:
# start of make.prefs
WANT_WIN_X11=1
WANT_WIN_TTY=1
WANT_WIN_CURSES=1
c2x=1
resp=1
# end of make.prefs
Now, my make command just needs to specify a target:
make update
The syntax for checking whether make.prefs exists, and for including
it, is GNU make, or bsd make, specific, so sys/unix/mkmkfile.sh will
insert the correct syntax for the make that is in-use when
sys/unix/setup.sh is executed.
The 'make.prefs' file isn't limited to Makefile variable assignments, and
can contain any valid make syntax for the version of make on your system,
but adding make syntax beyond Makefile variable assignment will cause
your make.prefs file to become specific to that version of make. There
are syntactical differences between GNU make and bsd make, particularly
for directives and conditional tests.
The 'make.prefs' file can potentially eliminate much/all of the manual
editing of distributed repository Makefiles or hints files that you, as
a NetHack developer or builder, might routinely carry out.
You have the option of placing your preference changes in 'make.prefs'
instead.
Related reference for .500 hints file variables:
In the NetHack source tree:
sys/unix/README.hints
On GitHub:
https://github.com/NetHack/NetHack/blob/NetHack-5.0/sys/unix/README-hints
For example, on macOS, where GNU make is being used, and I typically
set things up using the macOS.500 hints file:
sys/unix/setup.sh sys/unix/hints/macOS.500
I might have the following make.prefs in the root of my NetHack source tree:
#---- snip -------
$(info Attention - Using make.prefs)
WANT_MACSOUND=1
resp=1
#---- end-snip ---
For another example, on Linux, where GNU make is being used, and I
typically set things up using the linux.500 hints file:
sys/unix/setup.sh sys/unix/hints/linux.500
I might have the following make.prefs file in the root of my NetHack
source tree:
#---- snip -------
$(info Using make.prefs)
WANT_WIN_X11=1
WANT_WIN_TTY=1
WANT_WIN_CURSES=1
c2x=1
resp=1
#---- end-snip ---
Buffer overflows could occur when interacting with containers while
inputting or outputting many items.
This commit ensures topline updates do not exceed buffer limits by
checking against TBUFSZ.
Issue reported by k21971 on IRC.
In past releases of NetHack, there was a myriad of different hints
files for different operating systems, and even different versions
of operating systems.
It made maintenance a chore, because all the variable hints files
had to be updated for a wanted change, or (as typically was the
case), some lesser-used hints files were left behind and became
outdated.
Instead of going down that road again, this renames
sys/unix/hints/netbsd.500
to
sys/unix/hints/bsd.500
Where things need to differ for a different bsd flavour,
the differences can be shrouded in things like
.if ${WHICHBSD} == "NETBSD"
.else
.endif
This change is being done to make maintenance easier, at the
cost of making the resulting Makefiles a little more complex,
but there won't be as many separate Makefile hints to maintain.
This commit is being done instead of merging pull request #1531
which would add a new sys/unix/hints/openbsd.500 file.
Only tested on NetBSD so far. Please let us know if there's
an issue on other bsd's, and we will attempt to fix thos issues.
Closes#1531
Close
When a random statue or a figurine was generated in special levels,
the gender was not initialized correctly, so you ended up getting
eg. "dwarf ruler"
It now works correctly, and you can still specifically request
a non-gendered version with the montype-parameter.
For example
des.object({ id = "statue" });
des.object({ id = "statue", montype = "dwarf ruler" });
The gnome king statue in minetn-5 was generated as a gnome leader,
obey the gender of the statue name, so generating a statue of
for example "gnome king" and "gnome queen" works correctly.
Originating from https://github.com/NetHack/NetHack/pull/1519,
there was an issue with the pull request's back-end fork or with
the pull request itself.
The code changes were applied manually instead, with credit to the
pull request's author, instead of being directly merged in via the
pull request.
Contributed by @SirWumpus on GitHub.
Also,
- fixed a bit of conditional code in include/unixconf.h, where the
#else clause remained out of reach for non-bsd systems, but was
needed..
- added a disclaimer to the contributed sys/unix/hints/netbsd.500.
amii_outrip relies on LoadRGB4/transpalette fade and raw BltBitMap
to a SMART_REFRESH window -- chipset-era idioms that do not reach
the visible display on Picasso96 or CyberGraphX screens. On RTG
the screen stayed black and the user saw nothing between the
death messages and the high-score list. Detect RTG by screen
size > 800x600 and fall through to genl_outrip so RTG users get
the ASCII tombstone instead.
Switch the still-graphical path to BltBitMapRastPort so the blit
goes through the layer system, and move CloseWindow(ripwin)
outside the Forbid()/Permit() pair (same fix as amii_cleanup).
Rename cmap_white/cmap_black to cmap_outline/cmap_fill -- those
variables actually hold the indices of the darkest and lightest
palette entries, used for the four offset outline strokes and
the centered fill stroke respectively; the old names were
backwards.
The amii_get_ext_cmd menu used the first character of each command
as the item identity (id.a_char) and then linearly searched
extcmdlist for the first command starting with that character.
Many commands share a first letter, so picking #airlevel returned
#adjust, #wipe returned #wear, etc. Store the actual index in
id.a_int and read it back directly.
While in that function, size obufp at BUFSZ (was 100) and replace
the unbounded strcpy from extcmdlist[i].ef_txt with strncpy +
explicit NUL.
Reject tile/tomb IFF files whose nPlanes field exceeds DEPTH:
the CMAP loop writes 1<<np entries into amii_initmap[] /
amiv_init_map[], both sized AMII_MAXCOLORS = 1<<DEPTH = 64, so
a malformed file with nPlanes >= 7 would corrupt adjacent BSS.
After OpenScreen succeeds, clamp amii_numcolors to the actually
populated portion of the init-map arrays (AMII_PALETTE_SIZE for
text mode, AMIV_PALETTE_SIZE for tile mode). On a 64-color
screen this stops LoadRGB4 from loading the zero-initialized
tail entries as black. Replace the matching magic 32 in the
tilefile selection with AMIV_PALETTE_SIZE.
While there, add the (char) cast on amii_glyph_buffer's
truncating assignment to make the contract explicit.
When a single word exceeds the visible message-window width the
wrap loop found no whitespace, called outmore(cw), and continued
without advancing str -- and on the next iteration curx==0 took
it straight back to the same spot. Force-break the word at the
column boundary when we are already at the start of a line.
Also reset the wrapping static flag to 0 after the NHW_BASE wrap
cleanup runs, so the cleanup fires once after a wrap instead of
on every subsequent putstr.
Make the BufferQueueChar macro bounds-check KbdBuffered against
KBDBUFFER internally so the RAWKEY and NEWSIZE 'R'-64 paths can
no longer push past the 10-byte queue; widen KbdBuffered to int
so the counter cannot wrap silently in the queue-scan loops.
In amii_cleanup move kill_nhwindows()/DeleteMsgPort() outside
the Forbid()/Permit() pair: CloseWindow can wait on layers.library
semaphores on OS 3.x and that is unsafe under Forbid. Keep only
the IDCMP-flush loop inside.
Guard the gd lookup in DoMenuScroll's GADGETUP/MOUSEMOVE branches
so a window with no GadgetID==1 does not deref NULL; match the
existing guards in the keyboard-scroll branches. In the keyboard
selector and MENU_UNSELECT_ALL paths, only mutate items with
canselect set so a non-selectable header cannot have its str
stomped. Clamp MENU_LAST_PAGE topidx to >= 0. Make find_menu_item
return NULL on negative idx instead of the head item. Guard the
PROMPTFIRST data[] shuffle behind cury > 0.
In amii_destroy_nhwindow's NHW_OVER branch use cw->win with a NULL
guard instead of dereferencing amii_wins[WIN_OVER]->win blindly.
Range-check the type argument to amii_create_nhwindow. Fix the
*argv_in[1] precedence bug so the -L/-l flag does not deref NULL
when it is the last argument. Wrap AllocAslRequest result in a
NULL check before AslRequestTags/FreeAslRequest.
Defensively bounds-check the idx argument to DispCol. Replace
the -25937 signed-int literal in clipwin's PropInfo with the
equivalent UWORD value 39599. Simplify amii_start_menu's free
loop; switch DoMenuScroll's inventory title and Count display to
Snprintf, and stop passing countString to pline as a format.
Right-size the Intuition string-gadget buffer to BUFSZ so a caller
with a BUFSZ-sized buffer cannot be overflowed. Enlarge the
amii_yn_function prompt buffer to fit the worst-case query + resp
+ def + trailing space and switch the appends to Snprintf with
remaining-space tracking. Replace sprintf in amii_display_file's
"Can't display X: Y" path with Snprintf. In EditColor's Save path
drop the strcpy/strcat chain that could trail off the end of
oname/nname when dirname returned a near-full path; use Snprintf
instead. Rewrite dirname() to copy first and truncate the copy,
so it no longer briefly NULs the caller's string.
Add AMII_PALETTE_SIZE / AMIV_PALETTE_SIZE in amiconf.h to make the
actual populated portion of the init-map arrays explicit. Drop the
redundant extern void exit() declaration. Annotate Abort with
NORETURN in both amiconf.h and winproto.h; drop the duplicate Abort
declaration further down winproto.h.
Convert the bare-token "CLIPPING must be defined" assertion in
windefs.h into a real #error directive.
Comment in winext.h to disambiguate the three similarly named
amii*_init*map palette arrays.
The UNTESTED #ifdef in freediskspace was never gated by any hints
file, so the unsigned-long-long path could only be enabled by a
stray manual #define -- in which case the return type is still
long and silently truncates. Remove the branches.
In fopenp the separator '/' write was unchecked: when the path
segment exactly filled the buffer to BUFSIZ-2 it would land at
buf[BUFSIZ-1] and the follow-on NUL would write past the end.
Guard the write.
Replace #pragma-pack BMP header reads with little-endian byte
readers so the tool works on any host endianness. Add dimension
and color-count range checks, zero-init pixel remap table, check
calloc, free bmpdata on early returns, send malloc errors to
stderr. Add bp>xbuf guards to xpmgetline's strip loop.
- amii_set_text_font called CloseLibrary(DiskfontBase) outside the
OpenLibrary guard; on Kickstart V36+ that is a no-op for a NULL
handle, but on V33/V34 it is undefined. Move the close inside
the if-block where DiskfontBase is known non-NULL.
- amii_get_ext_cmd's bounds check used BUFSZ for an obufp[100]
buffer; the tighter COLNO check actually bounded it but the
expression was misleading. Use sizeof obufp.
- MyAllocBitMap left bm->bm.Planes[] uninitialized; InitBitMap only
fills BytesPerRow/Rows/Flags/Depth, not Planes[]. If AllocRaster
fails mid-loop, MyFreeBitMap was iterating up to Depth and would
pass uninitialized stack-garbage pointers to FreeRaster. Zero
Planes[] before the alloc loop.
- ReadImageFile leaked iffparse.library, the IFFHandle, the DOS file
handle, and any open-IFF state on every panic path. On AmigaOS
those handles are not auto-reclaimed when the process dies, so
each failure stranded resources until reboot. Restructure to a
single cleanup label and free in reverse-acquisition order before
panicking.
- OpenIFF returns an error code that was being thrown away, so a
failed open would feed corrupt state to ParseIFF. Check and
bail.
- MyAllocBitMap left bm->mflags uninitialized, so MyFreeBitMap took the
wrong path between FreeRaster and FreeMem and intermittently corrupted
exec's free list (Software Failure 0x81000005, DEADEND in FreeMem).
- The NHW_OVER window is BORDERLESS, so attaching WINDOWSIZING |
WINDOWDRAG | WINDOWCLOSE created phantom gadgets that hit-test against
unrelated input. Pressing ESC while the overview was selected fired
CLOSEWINDOW and destroyed the window underneath the running code,
leading to wild-PC crashes. Drop the gadget flags; SHIFT-HELP already
toggles the overview cleanly via delayed_key_action.
- amii_destroy_nhwindow only reset WIN_MAP / WIN_STATUS / WIN_MESSAGE /
WIN_INVEN; WIN_OVER and WIN_BASE kept pointing at freed slots, so any
later 'WIN_X != WIN_ERR && amii_wins[WIN_X]->win' check dereferenced
NULL. Reset them too.
Without the dependency, 'make amigapkg' would copy whatever was
already in targets/amiga/ without ever rebuilding when sources
changed -- silently shipping a stale binary.
- fname[18]/sprintf risks overflow for >=10 in any version field;
switch to snprintf into a wider static buffer.
- (1L << i) for i==31 (or shifting into the depth-loop terminator)
is undefined for signed long; use 1UL.
- Drop unused cnt= from amii_display_nhwindow's DoMenuScroll call;
the menu return value is consumed elsewhere, not here.
When a vault guard is being moving off the map to <0,0> to wait until
his temporary corridor gets removed, don't try to update the map for
that off-the-screen location in order to avoid triggering impossible()
from newsym().
Plus a trivial tweak to NH_abort(). Its argument is never modified so
declare it as such.
DoMenuScroll dropped IDCMP messages for non-owner windows -- so a
resize of WIN_INVEN or close-gadget on WIN_OVER during a menu never
reached the game state. Forward those to ProcessMessage;
VANILLAKEY/RAWKEY stay with the menu.
The macros were strcmp("amiv", windowprocs.name)==0 at every reference
-- 72 sites including inner loops. Use the 5.0 core's WINDOWPORT(wn)
which compares wp_id.
Tile loading hard-coded "NetHack:tiles/tiles{16,32}.iff" and PORT_HELP
hard-coded "nethack:amii.hlp". Route through fqname(DATAPREFIX) so
DATADIR= overrides apply. Refresh amii.hlp to 5.0 content, ship it via
amigapkg, and document HACKDIR / SAVEDIR / BONESDIR examples in
nethack.cnf.
Remove legacy compiler guards and stale extern declarations (the
ami_wbench_* family, CopyFile, ami_argset, ami_mkargline, FromWBench).
Drop unused AMII_*_VOLUME / DEFAULT_ICON macros and the
IDCMP_CLOSEWINDOW auto-define.
Delete amigst.c (empty) and amitty.c (TTY/BBS stub). Drop WINVERS_AMIT,
SUPERBITMAP_MAP, EXTMENU, SHELL/dosh(), and the bbs_id reference in
src/files.c.
- NHW_BASE / NHW_OVER collided with NHW_PERMINVENT=6; renumber off NHW_LAST_TYPE.
- GlyphToIcon used > 10000 instead of >=.
- make_menu_items sized array by sizeof(amii_menu_item) instead of menu_item.
- DoMenuScroll could deref NULL amip on SELECTUP.
- get_nhuuid uses ISAAC64 rn2() instead of hand-rolled LCG.
- fopenp's bound check fired one byte too late.
- winami.p had stale signatures for amii_end_menu, amii_select_menu, amii_suspend_nhwindows.
All the files in outdated are mostly source as they were prior to
the move to the outdated part of the NetHack tree. They are left
there in case somone wants to try to resurrect a port.
They are not meant to be compiled, or used as-is.
A remnant hard-coded 370 was in package.nmake.
Note: The errant file was not used to construct the official
binaries. Those were done using sys/windows/Makefile.nmake.
Closes#1525
Add Makefile support for an optional AMIGPKGSEQ to
append a suffix to the Amiga binary, without having to
rename the zip file manually after the
make CROSS_TO_AMIGA=1 package
step.
Core changes routed transient inventory away from WIN_INVEN, so the
port's win == WIN_INVEN gate stopped matching and glyphs vanished.
Track has_glyphs on the menu and key rendering and sizing off that.
I noticed that the "Dungeons & Dragons" trademark acknowledgement should
be using the _registered_ trade mark sign instead of the more general
one, as the mark's enjoyed registered status (in the U.S.) since 1978.
https://tmsearch.uspto.gov/search/search-results/73123558
It occurred to me that updating the game description for a 2026 audience
might be an improvement on one that assumes the reader is familiar with
D&D, with Teletype machines ("TTYs"), and with the Rogue game, which
NetHack arguably eclipsed in notoriety decades ago.
So I rewrote it, and dropped the references to D&D. Besides, as of
commit c99da87c70, NetHack is incompatible with "Strength Table I." in
the AD&D Player's Handbook (TSR 2010, p. 9), so any grognard who lifts
would snatch NetHack's D&D membership card away anyway. ;-)
...where available.
groff_man_style(7):
Notes
...
• When and how should I use quotation marks?
... groff, Heirloom Doctools troff, neatroff, and mandoc support
all of the special characters \[oq], \[cq], \[lq], \[rq], \[aq],
and \[dq] described in subsection “Portability” above. DWB, Plan
9, and Solaris troffs do not. Interpolating the strings \*(lq
and \*(rq portably yields directional double quotation marks, if
available, in all these formatters (though neatroff does not
supply a man macro package), but they cannot reliably be used in
macro arguments.
* Set cross reference to "nethack" man page in lowercase, because that's
the name under which it's installed, and POSIX systems are
case-sensitive.
* Refer to the "nethack" command using a man page cross reference only
on its first occurrence.
* Favor bullets over hyphens for itemized list.
* Drop explicit indentation amounts from lists. The man(7) package's
default suffices on all of Solaris 10, DWB 3.3, Plan 9, Heirloom
Doctools, and GNU *roffs, and on mandoc(1).
* Use tagged paragraphs to set synopses of syntax productions used in
the documented file format.
* Drop inset (indentation) of itemized and tagged lists; the bullets
make the structure clear, and (with the foregoing change) this way the
paragraphs align.
* Identify NETHACKDIR and HACKDIR as environment variables.
* ...and set them italics, not roman.
* Set default playground directory name in italics, not roman.
* Set command names in italics.
* Refer to command operands as such, not as "options".
* Use man page cross reference on first occurrence of "nethack" when
referring to the command executable as opposed to the overall game.
Because some text is commented out (`ig`nored), meaning the "first"
occurrence appears twice (what's lexically present vs. what's
formatted) do this twice as future-proofing.
* Set file names in italics, not roman. Set variable parts of file
names in roman.
* Refer to "single-user systems" instead of "microcomputers"; the latter
is becoming antiquated terminology.
* Favor present tense over future.
* Tighten wording.
* Spell "save files" consistently as two words.
Tighten formatting: set synopsis syntax characters adjacently to
operands. Rename `-d` option argument from "directory" to
"playground-directory" for clarity.
Set operands more idiomatically. They are not given in pairs; instead
"base" can be repeated arbitrarily. See, for example, the POSIX
reference page for ls(1).
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/ls.html
Format ellipsis idiomatically.
groff_man_style(7):
Notes
... The idiomatic roff ellipsis is three dots (periods) with thin
space escape sequences \| internally separating them. Since dots
both begin control lines and are candidate end‐of‐sentence
characters, however, it is sometimes necessary to prefix and/or
suffix an ellipsis with the dummy character escape sequence \&.
...on typesetters and UTF-8 terminals.
groff_man_style(7):
Portability
...
Several special characters are also widely portable. Except for
\-, \[em], and \[ga], AT&T troff did not consistently define the
characters listed below, but its descendants, like DWB, Plan 9, or
Solaris troff, can be made to support them by defining them in font
description files, making them aliases of existing glyphs if
necessary; see groff_font(5). groff’s extended notation for
special characters, \[xx], is also supported by mandoc(1), Heirloom
Doctools troff, and neatroff, but not DWB, Plan 9, or Solaris
troffs.
...
\[ha] Basic Latin circumflex accent (“hat”). Some output devices
format “^” as U+02C6 (modifier letter circumflex accent).
Notes
Some tips on composing and troubleshooting your man pages follow.
...
• Escape sequences of the form \[xx] don’t format correctly.
The \[xx] special character escape sequence is a GNU troff
extension also supported by mandoc, Heirloom Doctools troff, and
neatroff. DWB, Plan 9, and Solaris troffs don’t implement it.
If your man page requires portability to these formatters, spell
such escape sequences as “\(xx”; no closing parenthesis is used.
xx must be exactly two characters; groff_char(7) lists portable
special character identifiers.
Revise presentation of backward-compatible role options.
- Give them a metasyntactic variable name and present them in the main
command synopsis.
- Present the possible values in a typographical display, indented with
filling disabled.
Set it as a hanging paragraph, as is idiomatic for Unix command
synopses. Tighten formatting: set synopsis syntax characters adjacently
to operands. Also drop explicit line breaks, permitting synopsis to
exercise the configured line length of the selected output device.
Temporarily disable adjustment in a manner more friendly to the system's
(or user's) configuration.[1] Stop attempting to manipulate
hyphenation; there's no portable way to do that.[2]
Before and after, as rendered with Solaris 10, DWB 3.3, and Plan 9
troffs:
- nethack [ -d|--directory directory ] [ -w|--windowtype
- interface ]
- [ --nethackrc:rc-file | --no-nethackrc ] [ -n ] [ -dec |
- -ibm ]
- [ -u player-name ] [ -X | -D ] [ -p profession ] [ -r race ]
- [ -@ ]
+ nethack [-d|--directory directory]
+ [-w|--windowtype interface]
+ [--nethackrc:rc-file|--no-nethackrc] [-n] [-dec|-ibm]
+ [-u player-name] [-X|-D] [-p profession] [-r race] [-@]
Not shown: Literal text is in bold, and option arguments in italics.
(Full disclosure: The aforementioned formatters use different page
offsets [left margin sizes], and Plan 9 nroff doesn't render _any_
typeface changes, ever, for any document using any macro package.)
Before and after, as rendered with groff, mandoc, and Heirloom Doctools
troff:
- [ --nethackrc:rc-file | --no-nethackrc ] [ -n ] [ -dec | -ibm ]
- [ -u player-name ] [ -X | -D ] [ -p profession ] [ -r race ] [ -@ ]
+ nethack [-d|--directory directory] [-w|--windowtype interface]
+ [--nethackrc:rc-file|--no-nethackrc] [-n] [-dec|-ibm]
+ [-u player-name] [-X|-D] [-p profession] [-r race] [-@]
(Full disclosure: groff 1.24.x man(7) uses a default line length of
80n,[3] up from the 78n of its previous releases going back to 2002, and
used by Heirloom Doctools and mandoc.)
[1] https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/tmac/an.tmac?h=1.24.1#n159
[2] https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/tmac/an.tmac?h=1.24.1#n202
[3] https://cgit.git.savannah.gnu.org/cgit/groff.git/tree/NEWS?h=1.24.1#n509
Set it as a hanging paragraph, as is idiomatic for Unix command
synopses. Tighten formatting: set synopsis syntax characters adjacently
to operands. Since viewing the scoreboard is a separate mode of
operation, arrange first the options that select this mode.[1] Also
drop explicit line breaks, permitting synopsis to exercise the
configured line length of the selected output device.
Before and after, as rendered with Solaris 10 troff:
- nethack [ -d|--directory directory ] -s|--scores [ -v ]
- [ -p profession ] [ -r race ] [ player-name ...]
+ nethack {-s|--scores} [-d|--directory directory] [-v]
+ [-p profession] [-r race] [player-name ...]
Before and after, as rendered with groff, mandoc, and Heirloom Doctools
troff:
- nethack [ -d|--directory directory ] -s|--scores [ -v ]
- [ -p profession ] [ -r race ] [ player‐name ...]
+ nethack {-s|--scores} [-d|--directory directory] [-v] [-p profession]
+ [-r race] [player‐name ...]
Not shown: Literal text is in bold, and option arguments in italics.
[1] See, for example,
<https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/utilities/compress.html>.
Define strings for directional single quotation marks.
groff_man_style(7):
Notes
Some tips on composing and troubleshooting your man pages follow.
...
• When and how should I use quotation marks?
...
Obtaining directional single quotation marks is more of a
challenge. Historically, man pages used ` and ', which troff
rendered on typesetters as ‘ and ’, exclusively for them.
However, in recent years, some distributors of groff have chosen
to override the meanings of these characters in man pages,
remapping them to their Unicode Basic Latin code points.
Unfortunately, ` and ' are the only reliable means of obtaining
directional single quotation marks in AT&T troff; in that
implementation, often no special character escape sequences exist
to obtain them. Further, AT&T troff’s special character
identifiers, like its font names, were device‐specific. To
achieve quotation portably in man pages rendered both by AT&T and
more modern troffs, consider adding a preamble to your page after
the TH call as follows.
.ie \n(.g \{\
. ds oq \[oq]\"
. ds cq \[cq]\"
.\}
.el \{\
. ds oq `\"
. ds cq '\"
.\}
You must then use the \* escape sequence to interpolate the
quotation mark strings.
The command
.RB \*(oq "while !\& git pull; do sleep 10; done" \*(cq
retries an update from the repository until it succeeds.
If this procedure seems complex, petition your distributor to
revert their remapping of the ` and ' characters.
Unbreakable spaces in AT&T troff were always non-adjustable.
Define a string to use groff's `\~` extension if possible.
groff_man_style(7):
Portability
...
\~ Adjustable non‐breaking space. Use this escape sequence
to prevent a break inside a short phrase or between a
numerical quantity and its corresponding unit(s).
Before starting the motor,
set the output speed to\~1.
There are 1,024\~bytes in 1\~KiB.
CSTR\~#8 documents the B\~language.
\~ is a GNU extension also supported by Heirloom Doctools
troff 050915 (September 2005), mandoc 1.9.14
(2009‐11‐16), neatroff (commit 1c6ab0f6e, 2016‐09‐13),
and Plan 9 from User Space troff (commit 93f8143600,
2022‐08‐12), but not by DWB or Solaris troffs.
Fixes bad rendering in DWB 3.3 troff:
@@ -999 +999 @@
- file. -s|-s~-v may also be followed by arguments -p
+ file. -s|-s -v may also be followed by arguments -p
@@ -1005 +1005 @@
- entries which match both. -s|-s~-v may be followed by one
+ entries which match both. -s|-s -v may be followed by one
Solaris 10 troff _would_ misrender as well, but a different portability
problem keeps some of the foregoing text from rendering at all.
Old *roffs don't support the `ti` special character. Compensate.
Before (DWB, Solaris 10):
The --nethackrc:RC-file option will use RC-file instead of
the default run-time configuration file (typically
/.nethackrc) and the --no-nethackrc option can be used to
skip any run-time configuration file.
Before (Plan 9):
The --nethackrc:RC-file option will use RC-file instead of
the default run-time configuration file (typically
ti/.nethackrc) and the --no-nethackrc option can be used to
skip any run-time configuration file.
After (all):
The --nethackrc:RC-file option will use RC-file instead of
the default run-time configuration file (typically
~/.nethackrc) and the --no-nethackrc option can be used to
skip any run-time configuration file.
Favor the very old `lq` and `rq` extension _strings_ over special
characters of the same name. This fixes missing punctuation and text
when rendering this document with DWB and Solaris 10 nroffs, and
misrendered text with Plan 9 nroff.
Before (DWB, Solaris 10):
discovery mode (also known as explore mode). -D will start
the game in debug mode (also known as wizard mode) after
changing the character name to wizard, if the player is
allowed. Otherwise it will switch to -X. Control of who is
allowed to use debug mode is done via the
Before (Plan 9):
discovery mode (also known as explore mode). -D will start
the game in debug mode (also known as wizard mode) after
changing the character name to lqwizardrq, if the player is
allowed. Otherwise it will switch to -X. Control of who is
allowed to use debug mode is done via the lqWIZARDS=rq line in
NetHack's sysconf file.
After (all):
The -X option will start the game in a special non-scoring
discovery mode (also known as explore mode). -D will start
the game in debug mode (also known as wizard mode) after
changing the character name to "wizard", if the player is
allowed. Otherwise it will switch to -X. Control of who is
allowed to use debug mode is done via the "WIZARDS=" line in
NetHack's sysconf file.
(There are minor differences in the page offset amount, and Plan 9 uses
UTF-8 double quotation marks, U+201C and U+201D.)
groff_man(7):
Strings
The following strings are defined for use in man pages. None of
these is necessary in a contemporary man page; see
groff_man_style(7). ...
...
\*(lq
\*(rq interpolate special character escape sequences for left and
right double‐quotation marks, \(lq and \(rq, respectively.
(I see that I should reword the foregoing to something like "None is
necessary in man pages targeting only contemporary *roff formatters".)
History
... 4BSD (1980) added lq and rq strings. ... Unix System V (1988)
incorporated the lq and rq strings.
Except for EX/EE, James Clark implemented the foregoing features in
early versions of groff. ... Plan 9 from User Space’s troff ...
incorporated the lq and rq strings in 2025.
groff_man_style(7):
Notes
Some tips on composing and troubleshooting your man pages follow.
...
• When and how should I use quotation marks?
As noted above in subsection “Font style macros”, apply quotation
marks to “brief specimens of literal text, such as article
titles, inline examples, mentions of individual characters or
short strings, and (sub)section headings in man pages”. Multi‐
word literals, such as Unix commands with arguments, when set
inline (as opposed to displayed between EX and EE), should be
quoted to ensure that the boundaries of the literal are clear
even when the material is stripped of font styling by, for
example, copy‐and‐paste operations. groff, Heirloom Doctools
troff, neatroff, and mandoc support all of the special characters
\[oq], \[cq], \[lq], \[rq], \[aq], and \[dq] described in
subsection “Portability” above. DWB, Plan 9, and Solaris troffs
do not. Interpolating the strings \*(lq and \*(rq portably
yields directional double quotation marks, if available, in all
these formatters (though neatroff does not supply a man macro
package), but they cannot reliably be used in macro arguments.
Per the final sentence above, do a little dance to avoid using these
strings in macro arguments.
Paragraphing macros in *roff systems generally break the output line,
and the same is true of all of man(7)'s paragraphing macros.
groff_man(7):
Paragraphing macros
These macros break the output line. An ordinary paragraph (P)
indents all output lines by the same amount. A hanging paragraph
(HP) is a cosmetic variant of P with a hanging indent. Definition
lists frequently occur in man pages; these can be set as tagged
paragraphs, which have one (TP) or more (TQ) leading tags followed
by a paragraph that has an additional indentation.
NetHack's man pages already preponderantly use man(7) `IR` macro for
this purpose. Align outliers.
The "SEE ALSO" section of doc/mn.7 is a partial exception. While the
rest of the document sets cross-referenced man page topics in italics,
this section of the page does not. It seems likely that this decision
was made in deliberate imitation of Seventh Edition Unix manuals (1979)
or their descendants in USG/USL and BSD Unices. That feature of the
Unix man pages, however, was not deliberate per Doug McIlroy, the author
of the man(7) macros and editor of Volume 1 of the Seventh Edition Unix
Programmer's Manual, per his communication on the groff mailing list.
But NetHack has a policy of not modifying Matt Bishop's "mn" macro
file or its man page, so I leave that exception in place.
References:
https://lists.gnu.org/archive/html/groff/2021-08/msg00023.htmlhttps://lists.gnu.org/archive/html/groff/2021-08/msg00040.htmlhttps://github.com/NetHack/NetHack/pull/977#issuecomment-1424996578
Sectioning and paragraphing macros always break the output line.
(Sub)sectioning macros always set text after the heading as a paragraph.
Fixes:
$ mandoc -T lint doc/*.[67] # output edited
doc/makedefs.6:49:2: WARNING: skipping paragraph macro: PP after SH
doc/nethack.6:367:2: WARNING: skipping paragraph macro: br after PP
doc/nethack.6:365:2: WARNING: skipping paragraph macro: PP empty
doc/nethack.6:157:2: WARNING: skipping paragraph macro: PP after SH
doc/nethack.6:431:2: WARNING: skipping paragraph macro: PP after SH
doc/nethack.6:673:2: WARNING: skipping paragraph macro: PP after SH
doc/nethack.6:676:2: WARNING: skipping paragraph macro: PP after SH
doc/recover.6:29:2: WARNING: skipping paragraph macro: PP after SH
doc/recover.6:125:2: WARNING: skipping paragraph macro: PP after SH
doc/recover.6:141:2: WARNING: skipping paragraph macro: PP after SH
doc/mnh.7:23:2: WARNING: skipping paragraph macro: PP after SH
doc/mnh.7:46:2: WARNING: skipping paragraph macro: PP after SH
Explain meaning of stacked paragraph tags naming environment variables.
Drop call of deprecated man(7) `DT` macro and invocation of `ta` request
to set tab stops to attempt table-like layout. (The latter made the
former nilpotent anyway.) Replace this material with calls of tagged
paragraphing macro `TP` and groff man(7)'s `TQ` extension for setting
multiple tags with a paragraph. The result takes up more screen lines,
but renders well with more formatters.
Set indentation of tagged paragraph using a constant numeric expression
to accommodate pseudo-roff formatters that don't implement arithmetic
evaluation. (Some of these ignore _any_ indentation, regardless.)
Slightly recast descriptions of environment variables.
Set file name literals in italics.
Protect file and environment variable names from hyphenation.
Fixes:
an.tmac:doc/nethack.6:608: style: use of deprecated macro: .DT
* Define string to exercise groff's hyphenless break point feature.
This helps with file names and URLs. On formatters that don't claim
compatibility with groff, define the string as nothing, getting the
same result as before (a _highly_ ragged right margin, jarring
adjustment, or overset lines).
* If the formatter does not claim compatibility with groff, define a
copy of groff man(7)'s `TQ` macro to ease stacking of paragraph tags.
* Set file name literals in italics. Stop quoting them (which was
inconsistently done anyway).
* Revise "FILES" section.
- Drop redundant `PP` paragraphing call.
$ mandoc -T lint doc/nethack.6
...
mandoc: doc/nethack.6:432:2: WARNING: skipping paragraph macro: PP after SH
...
groff_man(7):
.SH [heading‐text]
Set heading‐text as a section heading. ... Text lines after
the call are set as an ordinary paragraph (P).
- Drop call of deprecated man(7) `DT` macro and invocation of `ta`
request to set tab stops to attempt table-like layout. (The latter
made the former nilpotent anyway.) Replace this material with calls
of tagged paragraphing macro `TP` and groff man(7)'s `TQ` extension
for setting multiple tags with a paragraph. The result takes up
more screen lines, but renders well with more formatters.
- Fine-tune styling of file names.
groff_man_style(7):
Use italics for file and path names, ... for variant
(user‐replaceable) portions of syntax synopses, ... and
anywhere a parameter requiring replacement by the user is
encountered. An exception involves variant text in a
context already typeset in italics, such as file or path
names with replaceable components; in such cases, follow the
convention of mathematical typography: set the file or path
name in italics as usual but use roman for the variant part
(see IR and RI below), and italics again in running roman
text when referring to the variant material.
Solaris 10, DWB 3.3, and Plan 9 from User Space nroffs formatted the
table of file names and descriptions quite badly.
Before:
nethack The program itself.
Guidebook | Guidebook.txt NetHack's user manual.
data, oracles, rumors Data files used by NetHack.
bogusmon Another data file.
engrave, epitaph, tribute Still more data files.
symbols Data file holding sets of speci-
fications
for how to display monsters,
objects, and
map features.
options Data file containing a descrip-
tion of the
build-time option settings.
help, hh, cmdhelp Help data files. ('cmdhelp' is
obsolete.)
...
Now (pagination on AT&T nroffs is omitted):
nethack
The program itself.
Guidebook
Guidebook.txt
NetHack's user manual.
data
oracles
rumors
Data files used by NetHack.
bogusmon
Another data file.
engrave
epitaph
tribute
Still more data files.
symbols
Data file holding sets of specifications for how to
display monsters, objects, and map features.
options
Data file containing a description of the build-time
option settings.
help
hh
cmdhelp
Help data files. (cmdhelp is obsolete.)
Fixes:
an.tmac:doc/nethack.6:444: style: use of deprecated macro: .DT
Not a serious issue in my opinion, but worth fixing. DWB does not
misrender the document, and the "stack" referred to is not the runtime
stack employed by the operating system, but one in the *roff language
runtime.
The diagnostic appears to be spurious in this case, but it isn't always.
https://github.com/n-t-roff/DWB3.3/issues/10
No *roff known to me interprets arguments to the `br` request. They
don't complain, either, but some day that may change.
https://savannah.gnu.org/bugs/?61450
groff_man_style(7):
• Option dashes are specified with the \- escape sequence; this is
an important practice to make them clearly visible and to
facilitate copy‐and‐paste from the rendered man page to a shell
prompt or text file.
...
\- Minus sign. \- produces the basic Latin hyphen‐minus
(U+002D) specifying Unix command‐line options and frequently
used in file names. “-” is a hyphen in roff; some output
devices format it as U+2010 (hyphen).
...pacifying a warning from the forthcoming groff 1.25.
Fixes:
troff:doc/dlb.6:159: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:53: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:55: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:58: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:153: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:159: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:166: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:222: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:245: warning: end of sentence detected before end of text line [-w style]
troff:doc/makedefs.6:279: warning: end of sentence detected before end of text line [-w style]
troff:doc/mnh.7:30: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:225: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:226: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:230: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:234: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:236: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:524: warning: end of sentence detected before end of text line [-w style]
troff:doc/nethack.6:577: warning: end of sentence detected before end of text line [-w style]
troff:doc/recover.6:155: warning: end of sentence detected before end of text line [-w style]
Aligns with other NetHack man pages and fixes:
$ nroff -ww -z -rCHECKSTYLE=4 -man doc/*.[67]
an.tmac:doc/mnh.7:2: style: .TH missing fourth argument; suggest package/project name and version (e.g., "groff 1.23.0")
Replace instances of blank line paragraphing with `PP` macro calls.
There are three problems with the style of paragraphing that this commit
fixes.
1. A `br` break request is redundant with an adjacent blank text line.
2. A `br` request is also redundant with a paragraphing macro call.
3. When you use a paragraphing macro call instead of a blank text line,
you get the configured amount inter-paragraph space. When
typesetting with the man(7) package, the default inter-paragraph
space amount is 0.4v. A blank text line usually puts 1v of empty
space into the document.
See groff_man_style(7).
Fixes:
$ nroff -ww -z -rCHECKSTYLE=4 -man doc/*.[67]
an.tmac:doc/nethack.6:435: style: blank line in input
an.tmac:doc/nethack.6:442: style: blank line in input
an.tmac:doc/nethack.6:535: style: blank line in input
an.tmac:doc/nethack.6:539: style: blank line in input
an.tmac:doc/nethack.6:543: style: blank line in input
an.tmac:doc/nethack.6:568: style: blank line in input
an.tmac:doc/nethack.6:572: style: blank line in input
Unix terminal drivers started transitioning away from paper terminals
and toward video terminals, and therefore away from '#' and '@' as the
"erase" and "kill" characters, respectively, before NetHack was born.
groff_man_style(7):
Portability
...
\e Format the roff escape character on the output; widely
used in man pages to render a backslash glyph. It works
reliably as long as the “ec” request is not used, which
should never happen in man pages, and it is slightly more
portable than the more explicit \[rs] (“reverse solidus”)
special character escape sequence.
This change's purpose is to put things right in case the change I'm
proposing next to delete this language entirely gets reverted.
Also fix a case hidden by a comment.
Fixes:
$ nroff -ww -z -man doc/*.[67]
troff:doc/nethack.6:68: warning: escape character ignored before '@'
troff:doc/nethack.6:292: warning: escape character ignored before '@'
Fixes four issues that prevented `make WANT_LIBNH=1 all` from producing
a libnh.a that could be linked into a host program on macOS. Before
these patches, it built but the resulting archive was unusable: macOS
ld errored on a nested liblua archive member, was missing date.o and
hacklib symbols (`populate_nomakedefs`, `eos`, `lcase`, `mungspaces`,
...), and had duplicate definitions of `main`, `whoami`, etc.
Specific changes:
1. sys/libnh/libnhmain.c: drop `static` on `whoami()`. src/earlyarg.c
declares it `extern` and calls it from `scores_only()`; the static
makes it file-local and that reference goes unresolved.
2. sys/libnh/libnhmain.c: gate the emscripten-only code in get_nhuuid
with `#ifdef __EMSCRIPTEN__` instead of `#ifdef NHUUID`. The macOS
hints define NHUUID for the libnh build (they did so unconditionally
before NO_NHUUID even existed), so on native builds the compiler
tried to call `emscripten_run_script_int` / `_string` and failed
with implicit-function-declaration errors. __EMSCRIPTEN__ is the
real signal for "this is being cross-compiled to WASM."
3. sys/unix/hints/macOS.500: in the WANT_LIBNH block, add an explicit
`recover: lua_support` dependency (gated by MAKEFILE_TOP). When
$(GAME) is overridden to empty, the regular `recover: $(GAME)` chain
no longer triggers `lua_support`, so include/nhlua.h never gets
generated and recover.c's transitive #include of hack.h fails.
4. sys/unix/hints/macOS.500: rewrite the libnh.a rule. The previous
`ar rcs libnh.a $(HOBJ) $(LIBNHSYSOBJ) liblua-$(LUA_VERSION).a` had
four problems: (a) ar archives liblua.a as a single opaque member
that macOS ld can't dereference, (b) date.o (DATE_O, kept separate
from HOBJ) was never archived, so `populate_nomakedefs` and
`nomakedefs` were missing, (c) hacklib.a was likewise omitted, and
(d) HOBJ already contains $(SYSOBJ) (with unixmain.o) and $(WINOBJ)
(the tty windowport), which duplicated symbols from libnhmain.o /
winshim.o.
The fix uses `libtool -static` so hacklib.a and liblua's archive
have their members merged rather than nested, depends on $(LUALIB)
so lua_support runs first, includes $(DATE_O) and $(TARGET_HACKLIB),
and uses $(filter-out $(SYSOBJ) $(WINOBJ),$(HOBJ)) to drop the
duplicates.
Verified by clean rebuild on macOS 26 (arm64, Apple clang 17):
make spotless
make fetch-Lua
make WANT_LIBNH=1 all
and link-tested with a tiny harness that calls
shim_graphics_set_callback() against the resulting libnh.a.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bug report stated:
"If 'mention_decor' is set in config file or NETHACKOPTIONS,
starting the game tells you that you are standing on stairs
which lead out of the dungeon. But if you also start the
tutorial, you won't be on those stairs--they won't even exist
until the tutorial is exited.
The stairs message can't be suppressed until the program
knows whether the tutorial will be entered, and since
prompting is one of the ways to decide that."
What this does:
Don't heed mention_decor option during the primary rcfile()
processing.
Do heed it after the tutorial.
Note:
If mention_decor is expected to actually be active during the
tutorial, then the rcfile_only_this_option(opt_mention_decor)
likely has to be moved to a different line, which should be
easy enough.
The previous fix, while valid, still prompts for input during early
options processing if stdin is a tty. It really shouldn't be doing
that during early options such as --showpaths, so alter the placement
of the program_state.earlyoptions flag within *main().
GitHub issue https://github.com/NetHack/NetHack/issues/1513
Starting a new game, at the
'Shall I pick character's race, role, gender and alignment for you? [ynaq]'
prompt, the game shows as 'Version 5.0.0-0 Unix Work-in-progress'
but then once the game has started and you check #version you see
the correct 'Unix NetHack Version 5.0.0-0 post-release' feedback.
Closes#1513
Try using emscripten_run_script_string("crypto.randomUUID()");
I need to commit this to the repository to test it elsewhere.
If there isn't a revert shortly after this, it must have at least
built without issue.
Detect Workbench depth, display-database MaxDepth, and free chip RAM;
if any signals AMIV can't run (e.g. A1000 with 4-colour WB), swap
windowprocs to amii_procs before opening any screens.
SYSCF is for multi-user system-admin lockdown; single-user Amigas
don't need it, and assure_syscf_file() killing the binary when run
outside NetHack: was breaking normal launches.
Reference __stkinit so the linker pulls swapstack.o from libnix.a;
without it the program runs on the inherited shell stack and crashes
inside Lua / level-gen.
This feature was no longer fulfilling its intended purpose: the
issue is that when players are aware of it, instead of creating
interesting stories, it becomes a resource the player can rely on.
Alternative mitigation for some "unfair" early-game deaths has been
added (such as the warning shot for early-game attack wands and the
ability of iron shoes to protect against certain early traps), and
the warning shot in particular can create interesting gameplay
moments and stories of its own, especially when saving grace is
*not* present (discovering that a monster has a wand of fire and
can oneshot you is an interesting emergency situation, but less
scary if you know that its first attempt to oneshot you will fail).
The feature was also proving quite hard to code correctly, because
there are numerous cases that it "obviously" shouldn't affect
(most notably beheading due to Vorpal Blade, but also things like
purple worm digestion) which would need to be special-cased, and
because there are grey areas like wand zap bounces (which might or
might not be an intentional attempt by the player to hit themself
with the bounce) and damage from traps. Removing it saves the need
to work out, for every new damage source, whether and when saving
grace should interact with it.
Breaks save compatibility.
Version and history commands. Plus a quarter-assed description of the
versinfo option. ('mO' can update and possibly provide enough into to
make sense of it.)
\#history was already revised but the new description was inaccurate.
Guidebook.tex is untested.
Prevent the main vision_recalc loop from triggering an impossible for
bad coordinates from newsym(). This hack may mean that the underlying
problem will remain unsolved but at least newsym won't cause the fuzzer
to panic or frighten players with impossible warnings.
In earlier versions of NetHack, wands of digging generated fairly
often, allowing players to do a large amount of digging through the
maze walls in Gehennom and giving them a chance of an early escape
item.
In the current version, the need for both of these things has been
reduced: supply chests give a supply of early escape items
(including wands of digging), and Gehennom is no longer mostly made
of mazes with diggable walls. As such, there is no longer a reason
to generate wands of digging in such large numbers, even though it
was correct in the past.
This commit modifies some of the generation probabilities for wands
of digging in order to make them less abundant, in order to work
better with the code changes since the previous version.
Requested by Tomsod: change the break point for +2 damage bonus from
strength to be 18/50 instead of 18/51 so that gnome and orc heros can
achieve that 'naturally' by maxxing out Str.
Closes#1506
On macOS, the required underlying pieces are in there.
On Linux, we try to test for the presence of libuuid and
the uuid.h header files. If the tests are both successful,
we proceed to include NHUUID support.
On either macOS or Linux, NO_NHUUID=1 on the Make command
line will forcibly prevent the inclusion of the support for NHUUID.
Dungeoneers list updates
Ingo Paschke provided Amiga updates to get the port working
for the release to follow 3.6.7. He used the gcc-15.2 branch
of bebbo's Amiga toolchain on Linux.
G. Branden Robinson contributed several updates and suggestions to
help ensure that the *roff documentation production remains viable.
The traps don't disappear when stepped on any more; that should be
true even when monsters step on them.
(This bug was reported privately to me via IRC, rather than via the
devteam's email address, so there isn't a ticket number to close.)
New experimental option
This requires platform support to be useful. Currently an
implementation for Windows TTY console is included.
A Unix TTY implementation should be achievable I would think,
but I haven't pursued that, at least not yet (contributions welcome).
I'm not sure whether Qt or X11 interfaces offer a similar
timeout capability..
How it works:
When idlecheckpoint in on, if the wait for a new input is idle for
10 seconds (length of time to waite is controlled by
IDLECHECKPOINT_WAIT_TIME #define in hack.h), save_currentstate() is
called to bring everything up-to-date should a hangup or crash occur.
The input wait then continues/resumes.
The save_currentstate() call is only executed once per input request.
I have no idea whether this prevents the newly discovered impossible().
However, it does fix an obvious typo--in hindsight--that I made 6 years
ago (dealing with temporary lighting for camera flashes).
Issue reported by BartekCupial: segfault occurred and was tracked to
behavior of a rolling boulder trap. Suggested fix was included, but it
assumes that the destination spot is valid so is suspect.
A comment pointed out that the path is validated when a rolling boulder
trap is created so the segfault should be impossible. I didn't find an
explanation but am adding a fix based on the one in the issue report.
Closes#1490
A 37 character field for holding a unique identifier is added
to the save file, as well as to an ancestor field in bones files.
Since it requires installation of libuuid package on Linux,
it requires an exlicit WANT_NHUUID=1 on the Make command line there.
Without the libuuid support, the saved nhuuid is empty, which should
be harmless.
This also moves the save and restore of gm.moves higher up so that it
already has a value the first time it is used against a relative saved
timestamp.
Invalidates savefiles and bones files due to new fields.
I need to get this committed before I can test out the macOS portion,
so there may be some build issues there briefly (hopefully), and
follow-up commits to resolve them.
Increments EDITLEVEL.
Add a pointer to struct you, and put umonst there. Eliminate
the youmonst struct in gy.
The naming convention better matches the other u related fields,
and u.umonst has the same level of indirection as other monst pointers.
The u.umonst pointer is cleared prior to saving the parent u (struct you),
and u.umonst is reestablished upon restore.
Invalidates existing saves and bones due to the presence of the added
pointer field in struct you.
Windows stores things a bit differently.
Use a static function in consoletty.c to preserve that behavior,
but still utilize the core colortable[] array.
declare colortable[] const and no longer static so it can be shared
by code in window ports..
get rid of the Windows console port rgbtable and use the
core colortable[] instead.
utilize function colortable_to_int32() in Windows console instead
of the rgbtable_to_long() in the Windows port.
delete the Windows rgbtable_to_long() function.
remove unused hexval field (show it in a comment)
The rgb values should be the same as they were
previously, just expressed with hex values on the
table initialization.
-- NetHack may be freely redistributed. See license for details.
--
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.