Merge branch 'NetHack-3.7' into twitch-interact

This commit is contained in:
2026-04-13 15:05:44 -07:00
312 changed files with 15860 additions and 10846 deletions
+1
View File
@@ -96,3 +96,4 @@ bundle/*
util/*.lib util/*.lib
util/*.exp util/*.exp
submodules/CHKSUMS.tmp submodules/CHKSUMS.tmp
sys/amiga/regex/
+60 -61
View File
@@ -369,10 +369,11 @@ Using the cross-compiler, build the following targets:
src/dlb.c, src/do.c, src/do_name.c, src/do_wear.c, src/dlb.c, src/do.c, src/do_name.c, src/do_wear.c,
src/dog.c, src/dogmove.c, src/dokick.c, src/dog.c, src/dogmove.c, src/dokick.c,
src/dothrow.c, src/drawing.c, src/dungeon.c, src/dothrow.c, src/drawing.c, src/dungeon.c,
src/eat.c, src/end.c, src/engrave.c, src/exper.c, src/earlyarg.c src/eat.c, src/end.c, src/engrave.c,
src/explode.c, src/extralev.c, src/files.c, src/exper.c, src/explode.c, src/extralev.c,
src/fountain.c, src/getpos.c, src/glyphs.c, src/files.c, src/fountain.c, src/getpos.c,
src/hack.c, src/hacklib.c, src/insight.c, src/glyphs.c, src/hack.c, src/hacklib.c,
src/iactions.c, src/insight.c,
src/invent.c, src/isaac64.c, src/light.c, src/invent.c, src/isaac64.c, src/light.c,
src/lock.c, src/mail.c, src/makemon.c, src/mcastu.c, src/lock.c, src/mail.c, src/makemon.c, src/mcastu.c,
src/mdlib.c, src/mhitm.c, src/mhitu.c, src/minion.c, src/mdlib.c, src/mhitm.c, src/mhitu.c, src/minion.c,
@@ -413,7 +414,7 @@ Using the cross-compiler, build the following targets:
b) Lua (mandatory in 3.7) b) Lua (mandatory in 3.7)
lib/lua-5.4.6/src lib/lua-5.4.8/src
from sources: lua.c, lapi.c, lauxlib.c, lbaselib.c, lcode.c, from sources: lua.c, lapi.c, lauxlib.c, lbaselib.c, lcode.c,
lcorolib.c, lctype.c, ldblib.c, ldebug.c, lcorolib.c, lctype.c, ldblib.c, ldebug.c,
@@ -528,11 +529,11 @@ Cross-compiler pre-built binary downloads:
Disclaimer: This is a minimal recipe, just to help someone else get Disclaimer: This is a minimal recipe, just to help someone else get
started if they have a desire to get a full cross-compile of started if they have a desire to get a full cross-compile of
NetHack going for the Amiga. NetHack going for the Amiga.
See CAVEATS below.
Cross-compiler used: bebbo's amiga-gcc Cross-compiler used: bebbo's amiga-gcc
Cross-compiler url: https://github.com/bebbo/amiga-gcc Cross-compiler url: https://github.com/AmigaPorts/m68k-amigaos-gcc
Author of 3.7 support: Ingo Paschke
To our knowledge, a pre-built copy of the cross-compiler isn't available, To our knowledge, a pre-built copy of the cross-compiler isn't available,
so you will likely have to obtain the cross-compiler sources via git and so you will likely have to obtain the cross-compiler sources via git and
build it on your system. build it on your system.
@@ -542,86 +543,84 @@ Cross-compiler url: https://github.com/bebbo/amiga-gcc
sudo apt install make wget git gcc g++ lhasa libgmp-dev \ sudo apt install make wget git gcc g++ lhasa libgmp-dev \
libmpfr-dev libmpc-dev flex bison gettext texinfo ncurses-dev \ libmpfr-dev libmpc-dev flex bison gettext texinfo ncurses-dev \
autoconf rsync autoconf rsync libreadline-dev
The build prerequisite packages for macOS via homebrew are documented but The build prerequisite packages for macOS via homebrew are documented but
not tested by us any of us to date. not tested by us any of us to date.
brew install bash wget make lhasa gmp mpfr libmpc flex gettext \ brew install bash wget make lhasa gmp mpfr libmpc flex gettext \
texinfo gcc make autoconf gnu-sed texinfo gcc@12 make autoconf bison
After installing the prerequite packages and the cross-compiler After installing the prerequisite packages and the cross-compiler
it was a straightforward build: the build is straightforward:
git clone https://github.com/bebbo/amiga-gcc.git Create the /opt/amiga directory for holding the compiler and tools.
sudo mkdir /opt/amiga
sudo chgrp users /opt/amiga
sudo chmod 775 /opt/amiga
sudo usermod -a -G users username
(you may have to log off and back on)
Build the cross-compiler.
git clone https://github.com/AmigaPorts/m68k-amigaos-gcc.git amiga-gcc
cd amiga-gcc cd amiga-gcc
make update make update
[Note that you may have to take ownership of the files in the bebbo The compiler pieces are installed in /opt/amiga by default, and the
repo via chown before successfully carrying out the next steps] NetHack Makefiles expect them there.
make clean If you prefer, you can alter the prefix before you build if you want.
make clean-prefix The instructions for doing so were spelled out at the time of this writing at:
date; make all -j3 >&b.log; date
The compiler pieces are installed in /opt/amiga by default. If you prefer, https://github.com/AmigaPorts/m68k-amigaos-gcc
you can alter the prefix before you build if you want. The instructions Makefile adjustments will be needed, however.
for doing so were spelled out at the time of this writing at:
https://github.com/bebbo/amiga-gcc On your linux host:
On your linux host: # Clone NetHack 3.7 source
cd NetHack
cd sys/unix ; sh setup.sh hints/linux.370 ; cd ../.. sys/unix/setup.sh sys/unix/hints/linux.370
make fetch-lua make fetch-lua
make CROSS_TO_AMIGA=1 fetch-regex
On your macOS host:
cd sys/unix ; sh setup.sh hints/macOS.370 ; cd ../..
make fetch-lua
The Amiga cross-compile can then be carried out by specifying
CROSS_TO_AMIGA=1 on the make command line:
make CROSS_TO_AMIGA=1 all make CROSS_TO_AMIGA=1 all
make CROSS_TO_AMIGA=1 package make CROSS_TO_AMIGA=1 package
You can explicitly include tty and curses support if desired, otherwise The distribution ZIP is created at targets/amiga/NH370AMI.ZIP.
you'll end up with a tty-only cross-compile build. The SDL1 pdcurses
support has not been tested.
make WANT_WIN_TTY=1 WANT_WIN_CURSES=1 CROSS_TO_AMIGA=1 all On your macOS host, the Amiga cross-compile can be carried out by specifying
CROSS_TO_AMIGA=1 on the make command line:
# Clone NetHack 3.7 source
cd NetHack
sys/unix/setup.sh sys/unix/hints/macOS.370
make fetch-lua
make CROSS_TO_AMIGA=1 fetch-regex
make CROSS_TO_AMIGA=1 all
make CROSS_TO_AMIGA=1 package
Result: The "make package" target will bundle the (hopefully) necessary Result: The "make package" target will bundle the (hopefully) necessary
components to run NetHack on msdos into a folder: components to run NetHack on an Amiga into a folder:
targets/amiga/pkg targets/amiga/pkg
and then it zips the contents of that folder into: and then it zips the contents of that folder into:
targets/amiga/nh370ami.zip targets/amiga/NH370AMI.ZIP
Also note that building the amiga targets using the make command Display Modes
above, does not preclude you from building local linux or macOS -------------
targets as well. Just drop the CROSS_TO_AMIGA=1 from the make Two display modes are available, selected in nethack.cnf:
command line.
The cross-compiler hints additions are enclosed inside ifdef sections Text mode (AMII):
and won't interfere with the non-cross-compile build in that case. OPTIONS=symset:AmigaFont
CAVEATS: The original NetHack Amiga build steps included the source for Tile mode (AMIV):
some utilities that were built and executed on the amiga: OPTIONS=windowtype:amiv
txt2iff and xpm2iff
as part of the NetHack build procedure on amiga.
Those did not compile out-of-the-box on the linux host. They
will either have to be:
- ported to build and run on the linux or macOS cross-compile
host
or
- their functionality will have to be rolled into amiga NetHack Tile mode auto-selects tiles32.iff (32 colors, 5 bitplanes) when the
itself and executed on the target Amiga the first time the game screen supports 32+ colors, otherwise tiles16.iff (16 colors, 4 planes).
is run, perhaps.
For further details about playing the game, and setting up your NetHack
configuration, please see the following file:
sys/amiga/README.amiga
If you make headway, or are successful getting a working copy of
NetHack going on the amiga, drop us a note at devteam@nethack.org.
+--------------------------------+ +--------------------------------+
| B6. Case sample: Web Assembly | | B6. Case sample: Web Assembly |
@@ -646,7 +645,7 @@ Cross-compiler url: https://emscripten.org/docs/getting_started/downloads.html
For macOS, you will need to install Xcode, git, cmake, Python 3.5 or new For macOS, you will need to install Xcode, git, cmake, Python 3.5 or new
(at time of this writing). (at time of this writing).
After installing the prerequite packages above, obtain the cross-compiler After installing the prerequisite packages above, obtain the cross-compiler
via git and build it from the directory of your choice using steps similar via git and build it from the directory of your choice using steps similar
to these: to these:
+1 -1
View File
@@ -74,7 +74,7 @@ A. If you have never set up git on this machine before:
git config --global credential.helper osxkeychain git config --global credential.helper osxkeychain
Linux: Linux:
(This will vary by distribution.) (This will vary by distribution.)
cd /usr/share/doc/git/contrib/credentail/libsecret cd /usr/share/doc/git/contrib/credential/libsecret
sudo apt-get install libglib-2.0-dev libsecret-1-dev sudo apt-get install libglib-2.0-dev libsecret-1-dev
sudo make sudo make
git config --global credential.helper `pwd`/git-credential-libsecret git config --global credential.helper `pwd`/git-credential-libsecret
+3 -3
View File
@@ -397,7 +397,7 @@ sub cmdparse {
} }
if($opt{cmd} eq 'commit' && $opt{a} && $#in == -1){ if($opt{cmd} eq 'commit' && $opt{a} && $#in == -1){
# "git commit -a" does multiple things; we only care # "git commit -a" does multiple things; we only care
# about modigied files. # about modified files.
#XXX this assumes $RS is set properly for Windows - need to check that #XXX this assumes $RS is set properly for Windows - need to check that
my @x = split(/$::RS/,`git ls-files -m`); my @x = split(/$::RS/,`git ls-files -m`);
chomp(@x); chomp(@x);
@@ -661,7 +661,7 @@ is actually a directory, the program recurses into that directory tree.
Not all files found are re-written; only those with the attribute Not all files found are re-written; only those with the attribute
NHSUBST (for inline substitutions) or NH_DATESUB (for template NHSUBST (for inline substitutions) or NH_DATESUB (for template
substitution) are considered; finally those with no substitution substitution) are considered; finally those with no substitution
variables or no changes due to subtitution variables are not variables or no changes due to substitution variables are not
re-written. Unless changed by the options, files that have not re-written. Unless changed by the options, files that have not
changed are not affected. changed are not affected.
@@ -711,7 +711,7 @@ or the changes will be overwritten with the current date.)
=back =back
=head1 SUBSTITUTION VALRIABLES =head1 SUBSTITUTION VARIABLES
=over =over
+1 -1
View File
@@ -43,7 +43,7 @@ BEGIN {
# Set $is_sourcerepo while we're at it - same logic. # Set $is_sourcerepo while we're at it - same logic.
{ {
# Special case for running nhgitset against a different repo. # Special case for running nhgitset against a different repo.
# Must preceed the normal case! # Must precede the normal case!
# NB: we use $DEVhooksdir later in the program # NB: we use $DEVhooksdir later in the program
$DEVhooksdir = ($0 =~ m!^(.*)$DS!)[0]; $DEVhooksdir = ($0 =~ m!^(.*)$DS!)[0];
chomp($DEVhooksdir); chomp($DEVhooksdir);
+92 -81
View File
@@ -47,21 +47,21 @@ Val-strt.lua Wiz-fila.lua Wiz-filb.lua Wiz-goal.lua Wiz-loca.lua
Wiz-strt.lua air.lua asmodeus.lua astral.lua baalz.lua Wiz-strt.lua air.lua asmodeus.lua astral.lua baalz.lua
bigrm-1.lua bigrm-2.lua bigrm-3.lua bigrm-4.lua bigrm-5.lua bigrm-1.lua bigrm-2.lua bigrm-3.lua bigrm-4.lua bigrm-5.lua
bigrm-6.lua bigrm-7.lua bigrm-8.lua bigrm-9.lua bigrm-10.lua bigrm-6.lua bigrm-7.lua bigrm-8.lua bigrm-9.lua bigrm-10.lua
bigrm-11.lua bigrm-12.lua bogusmon.txt castle.lua cmdhelp bigrm-11.lua bigrm-12.lua bigrm-13.lua bogusmon.txt castle.lua
data.base dungeon.lua earth.lua engrave.txt epitaph.txt cmdhelp data.base dungeon.lua earth.lua engrave.txt
fakewiz1.lua fakewiz2.lua fire.lua hellfill.lua help epitaph.txt fakewiz1.lua fakewiz2.lua fire.lua hellfill.lua
hh history juiblex.lua keyhelp knox.lua help hh history juiblex.lua keyhelp
license luahelper medusa-1.lua medusa-2.lua medusa-3.lua knox.lua license luahelper medusa-1.lua medusa-2.lua
medusa-4.lua minefill.lua minend-1.lua minend-2.lua minend-3.lua medusa-3.lua medusa-4.lua minefill.lua minend-1.lua minend-2.lua
minetn-1.lua minetn-2.lua minetn-3.lua minetn-4.lua minetn-5.lua minend-3.lua minetn-1.lua minetn-2.lua minetn-3.lua minetn-4.lua
minetn-6.lua minetn-7.lua nhcore.lua nhlib.lua opthelp minetn-5.lua minetn-6.lua minetn-7.lua nhcore.lua nhlib.lua
optmenu oracle.lua oracles.txt orcus.lua quest.lua opthelp optmenu oracle.lua oracles.txt orcus.lua
rumors.fal rumors.tru sanctum.lua soko1-1.lua soko1-2.lua quest.lua rumors.fal rumors.tru sanctum.lua soko1-1.lua
soko2-1.lua soko2-2.lua soko3-1.lua soko3-2.lua soko4-1.lua soko1-2.lua soko2-1.lua soko2-2.lua soko3-1.lua soko3-2.lua
soko4-2.lua symbols themerms.lua tower1.lua tower2.lua soko4-1.lua soko4-2.lua symbols themerms.lua tower1.lua
tower3.lua tribute tut-1.lua tut-2.lua usagehlp tower2.lua tower3.lua tribute tut-1.lua tut-2.lua
valley.lua water.lua wizard1.lua wizard2.lua wizard3.lua usagehlp valley.lua water.lua wizard1.lua wizard2.lua
wizhelp wizard3.lua wizhelp
doc: doc:
(files for all versions) (files for all versions)
@@ -87,23 +87,23 @@ include:
tile2x11.h winX.h xwindow.h xwindowp.h tile2x11.h winX.h xwindow.h xwindowp.h
(files for all versions) (files for all versions)
align.h artifact.h artilist.h attrib.h botl.h align.h amiconf.h artifact.h artilist.h attrib.h
color.h config.h config1.h context.h coord.h botl.h color.h config.h config1.h context.h
cstd.h decl.h defsym.h dgn_file.h display.h coord.h cstd.h decl.h defsym.h dgn_file.h
dlb.h dungeon.h engrave.h extern.h flag.h display.h dlb.h dungeon.h engrave.h extern.h
fnamesiz.h func_tab.h global.h hack.h hacklib.h flag.h fnamesiz.h func_tab.h global.h hack.h
integer.h isaac64.h lint.h mail.h mextra.h hacklib.h integer.h isaac64.h lint.h mail.h
mfndpos.h micro.h mkroom.h monattk.h mondata.h mcastu.h mextra.h mfndpos.h micro.h mkroom.h
monflag.h monst.h monsters.h nhmd4.h nhregex.h monattk.h mondata.h monflag.h monst.h monsters.h
obj.h objclass.h objects.h optlist.h patchlevel.h nhmd4.h nhregex.h obj.h objclass.h objects.h
pcconf.h permonst.h prop.h quest.h rect.h optlist.h patchlevel.h pcconf.h permonst.h prop.h
region.h rm.h savefile.h seffects.h selvar.h quest.h rect.h region.h rm.h savefile.h
sfmacros.h sfprocs.h skills.h sndprocs.h sp_lev.h seffects.h selvar.h sfmacros.h sfprocs.h skills.h
spell.h stairs.h sym.h sys.h tcap.h sndprocs.h sp_lev.h spell.h stairs.h sym.h
tileset.h timeout.h tradstdc.h trap.h unixconf.h sys.h tcap.h tileset.h timeout.h tradstdc.h
vision.h vmsconf.h warnings.h weight.h winami.h trap.h unixconf.h vision.h vmsconf.h warnings.h
wincurs.h windconf.h winprocs.h wintype.h you.h weight.h winami.h wincurs.h windconf.h winprocs.h
youprop.h wintype.h you.h youprop.h
(file for tty versions) (file for tty versions)
wintty.h wintty.h
@@ -124,8 +124,8 @@ bitmfile.h gem_rsc.h load_img.h wingem.h
winGnome.h winGnome.h
(files for all versions) (files for all versions)
amiconf.h beconf.h def_os2.h os2conf.h system.h tosconf.h beconf.h def_os2.h os2conf.h system.h tosconf.h trampoli.h
trampoli.h wceconf.h wceconf.h
(files for various Macintosh versions) (files for various Macintosh versions)
mac-carbon.h mac-qt.h mac-term.h macconf.h macpopup.h mac-carbon.h mac-qt.h mac-term.h macconf.h macpopup.h
@@ -134,12 +134,7 @@ mactty.h macwin.h mttypriv.h
outdated/sys/amiga: outdated/sys/amiga:
(files for Amiga versions - untested for 3.7) (files for Amiga versions - untested for 3.7)
Build.ami Install.ami Makefile.agc Makefile.ami NetHack.cnf Build.ami Install.ami Makefile.agc Makefile.ami NetHack.cnf
amidos.c amidos.p amifont.uu amifont8.uu amigst.c ifchange mkdmake txt2iff.c xpm2iff.c
amii.hlp amimenu.c amirip.c amistack.c amitty.c
amiwind.c amiwind.p clipwin.c colorwin.c grave16.xpm
ifchange mkdmake txt2iff.c winamenu.c winami.c
winami.p winchar.c windefs.h winext.h winfuncs.c
winkey.c winproto.h winreq.c winstr.c xpm2iff.c
outdated/sys/atari: outdated/sys/atari:
(files for Atari version - untested for 3.7) (files for Atari version - untested for 3.7)
@@ -296,29 +291,40 @@ allmain.c alloc.c apply.c artifact.c attrib.c ball.c
bones.c botl.c calendar.c cfgfiles.c cmd.c coloratt.c bones.c botl.c calendar.c cfgfiles.c cmd.c coloratt.c
date.c dbridge.c decl.c detect.c dig.c display.c date.c dbridge.c decl.c detect.c dig.c display.c
dlb.c do.c do_name.c do_wear.c dog.c dogmove.c dlb.c do.c do_name.c do_wear.c dog.c dogmove.c
dokick.c dothrow.c drawing.c dungeon.c eat.c end.c dokick.c dothrow.c drawing.c dungeon.c earlyarg.c eat.c
engrave.c exper.c explode.c extralev.c files.c fountain.c end.c engrave.c exper.c explode.c extralev.c files.c
getpos.c glyphs.c hack.c hacklib.c insight.c invent.c fountain.c getpos.c glyphs.c hack.c hacklib.c iactions.c
isaac64.c light.c lock.c mail.c makemon.c mcastu.c insight.c invent.c isaac64.c light.c lock.c mail.c
mdlib.c mhitm.c mhitu.c minion.c mklev.c mkmap.c makemon.c mcastu.c mdlib.c mhitm.c mhitu.c minion.c
mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c
monst.c mplayer.c mthrowu.c muse.c music.c nhlobj.c mondata.c monmove.c monst.c mplayer.c mthrowu.c muse.c
nhlsel.c nhlua.c nhmd4.c o_init.c objects.c objnam.c music.c nhlobj.c nhlsel.c nhlua.c nhmd4.c o_init.c
options.c pager.c pickup.c pline.c polyself.c potion.c objects.c objnam.c options.c pager.c pickup.c pline.c
pray.c priest.c quest.c questpgr.c read.c rect.c polyself.c potion.c pray.c priest.c quest.c questpgr.c
region.c report.c restore.c rip.c rnd.c role.c read.c rect.c region.c report.c restore.c rip.c
rumors.c save.c selvar.c sfbase.c sfstruct.c shk.c rnd.c role.c rumors.c save.c selvar.c sfbase.c
shknam.c sit.c sounds.c sp_lev.c spell.c stairs.c sfstruct.c shk.c shknam.c sit.c sounds.c sp_lev.c
steal.c steed.c strutil.c symbols.c sys.c teleport.c spell.c stairs.c steal.c steed.c strutil.c symbols.c
timeout.c topten.c track.c trap.c u_init.c uhitm.c sys.c teleport.c timeout.c topten.c track.c trap.c
utf8map.c vault.c version.c vision.c weapon.c were.c u_init.c uhitm.c utf8map.c vault.c version.c vision.c
wield.c windows.c wizard.c wizcmds.c worm.c worn.c weapon.c were.c wield.c windows.c wizard.c wizcmds.c
write.c zap.c worm.c worn.c write.c zap.c
submodules: submodules:
(files in top directory) (files in top directory)
CHKSUMS lua pdcurses pdcursesmod CHKSUMS lua pdcurses pdcursesmod
sys/amiga:
(files for Amiga versions)
README.amiga amidos.c amidos.p amifont.uu
amifont8.uu amigst.c amii.hlp amimenu.c
amirip.c amistack.c amitty.c amiwind.c
amiwind.p bmp2iff_host.c clipwin.c colorwin.c
grave16.xpm nethack.cnf winamenu.c winami.c
winami.p winchar.c windefs.h winext.h
winfuncs.c winkey.c winproto.h winreq.c
winstr.c xpm2iff_host.c
sys/libnh: sys/libnh:
(files in top directory) (files in top directory)
README.md libnhmain.c sysconf README.md libnhmain.c sysconf
@@ -418,6 +424,7 @@ sys/unix/hints/include:
compiler.370 cross-post.370 cross-pre1.370 cross-pre2.370 compiler.370 cross-post.370 cross-pre1.370 cross-pre2.370
gbdates-post.370 gbdates-pre.370 misc.370 multisnd-post.370 gbdates-post.370 gbdates-pre.370 misc.370 multisnd-post.370
multisnd1-pre.370 multisnd2-pre.370 multiw-1.370 multiw-2.370 multisnd1-pre.370 multisnd2-pre.370 multiw-1.370 multiw-2.370
response.370
sys/vms: sys/vms:
(files for VMS version) (files for VMS version)
@@ -430,7 +437,7 @@ vmsmain.c vmsmisc.c vmssetup.com vmstty.c
vmsunix.c vmsunix.c
sys/windows: sys/windows:
(files for Windows 7/8.x/10/11 version) (files for Windows 10/11 version)
GNUmakefile GNUmakefile.depend Install.windows GNUmakefile GNUmakefile.depend Install.windows
Makefile.nmake build-msys2.txt build-nmake.txt Makefile.nmake build-msys2.txt build-nmake.txt
build-vs.txt console.rc consoletty.c build-vs.txt console.rc consoletty.c
@@ -441,7 +448,7 @@ win10.c win10.h win32api.h
windmain.c windsys.c winos.h windmain.c windsys.c winos.h
sys/windows/vs: sys/windows/vs:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
NetHack.sln NetHackPackage.appxmanifest NetHack.sln NetHackPackage.appxmanifest
NetHackPackage.wapproj NetHackProperties.props NetHackPackage.wapproj NetHackProperties.props
Package.StoreAssociation.xml ScreenShot.PNG Package.StoreAssociation.xml ScreenShot.PNG
@@ -453,11 +460,11 @@ dirs.props dll.props
files.props sfctool.sln files.props sfctool.sln
sys/windows/vs/FetchPrereq: sys/windows/vs/FetchPrereq:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
fetchprereq.nmake fetchprereq.vcxproj fetchprereq.nmake fetchprereq.vcxproj
sys/windows/vs/Images: sys/windows/vs/Images:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
BadgeLogo.scale-100.png BadgeLogo.scale-100.png
BadgeLogo.scale-125.png BadgeLogo.scale-125.png
BadgeLogo.scale-150.png BadgeLogo.scale-150.png
@@ -512,71 +519,75 @@ Wide310x150Logo.scale-200.png
Wide310x150Logo.scale-400.png Wide310x150Logo.scale-400.png
sys/windows/vs/NetHack: sys/windows/vs/NetHack:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
NetHack.vcxproj afternethack.proj NetHack.vcxproj afternethack.proj
sys/windows/vs/NetHackW: sys/windows/vs/NetHackW:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
NetHackW.vcxproj NetHackW.vcxproj
sys/windows/vs/PDCurses: sys/windows/vs/PDCurses:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
PDCurses.vcxproj PDCurses.vcxproj
sys/windows/vs/PDCursesGui: sys/windows/vs/PDCursesGui:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
pdcursesgui.vcxproj pdcursesgui.vcxproj
sys/windows/vs/dlb: sys/windows/vs/dlb:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
afterdlb.proj dlb.vcxproj afterdlb.proj dlb.vcxproj
sys/windows/vs/fetchctags: sys/windows/vs/fetchctags:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
fetchctags.nmake fetchctags.vcxproj fetchctags.nmake fetchctags.vcxproj
sys/windows/vs/hacklib: sys/windows/vs/hacklib:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
hacklib.vcxproj hacklib.vcxproj
sys/windows/vs/lualib: sys/windows/vs/lualib:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
lualib.vcxproj lualib.vcxproj
sys/windows/vs/makedefs: sys/windows/vs/makedefs:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
aftermakedefs.proj makedefs.vcxproj aftermakedefs.proj makedefs.vcxproj
sys/windows/vs/nhlua_h:
(file for Visual Studio Community builds)
nhlua_h.vcxproj
sys/windows/vs/package: sys/windows/vs/package:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
package.nmake package.vcxproj package.nmake package.vcxproj
sys/windows/vs/recover: sys/windows/vs/recover:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
afterrecover.proj recover.vcxproj afterrecover.proj recover.vcxproj
sys/windows/vs/sfctool: sys/windows/vs/sfctool:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
sfctool.vcxproj sfctool.vcxproj
sys/windows/vs/sftags: sys/windows/vs/sftags:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
aftersftags.proj sftags.vcxproj aftersftags.proj sftags.vcxproj
sys/windows/vs/tile2bmp: sys/windows/vs/tile2bmp:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
aftertile2bmp.proj tile2bmp.vcxproj aftertile2bmp.proj tile2bmp.vcxproj
sys/windows/vs/tilemap: sys/windows/vs/tilemap:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
aftertilemap.proj tilemap.vcxproj aftertilemap.proj tilemap.vcxproj
sys/windows/vs/tiles: sys/windows/vs/tiles:
(file for Visual Studio 2019 or 2022 Community Edition builds) (file for Visual Studio Community builds)
tiles.vcxproj tiles.vcxproj
sys/windows/vs/uudecode: sys/windows/vs/uudecode:
(files for Visual Studio 2019 or 2022 Community Edition builds) (files for Visual Studio Community builds)
afteruudecode.proj uudecode.vcxproj afteruudecode.proj uudecode.vcxproj
test: test:
@@ -631,8 +642,8 @@ win/share:
(files for versions using optional tiles) (files for versions using optional tiles)
bmptiles.c gifread.c giftiles.c monsters.txt nhicns.uu bmptiles.c gifread.c giftiles.c monsters.txt nhicns.uu
nhsplash.xpm objects.txt other.txt ppmwrite.c renumtiles.pl nhsplash.xpm objects.txt other.txt ppmwrite.c renumtiles.pl
safeproc.c thintile.c tile.doc tile.h tile2bmp.c thintile.c tile.doc tile.h tile2bmp.c tilemap.c
tilemap.c tileset.c tiletext.c tiletxt.c tileset.c tiletext.c tiletxt.c
win/shim: win/shim:
(file in top directory) (file in top directory)
+1 -1
View File
@@ -201,7 +201,7 @@ need to be included in the packaging of the game.
4.3. Lua 4.3. Lua
Compile and link into a library, or obtain a prebuilt Lua library for Compile and link into a library, or obtain a prebuilt Lua library for
your platform. Place the Lua source into lib/lua-5.4.6 (or other folder your platform. Place the Lua source into lib/lua-5.4.8 (or other folder
representing an appropriate Lua version); place the compiled Lua library into representing an appropriate Lua version); place the compiled Lua library into
lib. lib.
+2 -2
View File
@@ -110,8 +110,8 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code.
Intel Pentium or better running Linux, BSDI Intel Pentium or better running Linux, BSDI
Intel Pentium or better running Windows 10 or 11 Intel Pentium or better running Windows 10 or 11
Intel-based, or Apple M1, M2, M3 Macs running Intel-based, or Apple M1, M2, M3, M4, M5 Macs running
macOS 10.11 (El Capitan) to macOS 14 (Sonoma) macOS 10.11 (El Capitan) to macOS 26 (Tahoe)
(follow the instructions in sys/unix/NewInstall.unx) (follow the instructions in sys/unix/NewInstall.unx)
Intel 80386 or greater running MS-DOS with DPMI Intel 80386 or greater running MS-DOS with DPMI
built via djgpp compiler (native or Linux-hosted cross-compiler) built via djgpp compiler (native or Linux-hosted cross-compiler)
+12 -6
View File
@@ -24,16 +24,21 @@ strategy:
imageName: 'macOS-15' imageName: 'macOS-15'
toolchainName: clang toolchainName: clang
buildTargetName: all buildTargetName: all
windows-visualstudio: windows-x64-vstudio:
imageName: 'windows-latest' imageName: 'windows-latest'
toolchainName: vs toolchainName: vs
buildTargetName: all buildTargetName: all
windows-arm64-vstudio:
imageName: 'windows-latest'
toolchainName: vs
buildTargetName: all
buildPlatform: 'ARM64' # Targeting Snapdragon
windows-mingw: windows-mingw:
imageName: 'windows-2025' imageName: 'windows-2025'
toolchainName: mingw toolchainName: mingw
buildTargetName: all buildTargetName: all
linux_noble_cross_msdos: linux_latest_cross_msdos:
imageName: 'ubuntu-24.04' imageName: 'ubuntu-latest'
toolchainName: cross toolchainName: cross
buildTargetName: msdos buildTargetName: msdos
linux_noble_docs: linux_noble_docs:
@@ -129,7 +134,7 @@ steps:
export LUASRC=../submodules/lua export LUASRC=../submodules/lua
export ADD_CURSES=Y export ADD_CURSES=Y
export PDCURSES_TOP=../submodules/pdcursesmod export PDCURSES_TOP=../submodules/pdcursesmod
export LUA_VERSION=5.4.6 export LUA_VERSION=5.4.8
# #
# 64-bit # 64-bit
#export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.1-12.0.0-ucrt-r2/winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.1-mingw-w64ucrt-12.0.0-r2.zip #export CURLSRC=https://github.com/brechtsanders/winlibs_mingw/releases/download/14.2.0posix-19.1.1-12.0.0-ucrt-r2/winlibs-x86_64-posix-seh-gcc-14.2.0-llvm-19.1.1-mingw-w64ucrt-12.0.0-r2.zip
@@ -227,6 +232,7 @@ steps:
- bash: | - bash: |
sudo apt -qq -y install libfl2 sudo apt -qq -y install libfl2
export GCCVER=gcc1220 export GCCVER=gcc1220
export IN_CI=SKIP_FONTS_IN_CI=1
cd sys/unix cd sys/unix
sh setup.sh hints/linux.370 sh setup.sh hints/linux.370
cd ../.. cd ../..
@@ -234,13 +240,13 @@ steps:
sys/msdos/fetch-cross-compiler.sh sys/msdos/fetch-cross-compiler.sh
retVal=$? retVal=$?
if [ $retVal -eq 0 ]; then if [ $retVal -eq 0 ]; then
make LUA_VERSION=5.4.6 WANT_WIN_TTY=1 WANT_WIN_CURSES=1 CROSS_TO_MSDOS=1 package make LUA_VERSION=5.4.8 WANT_WIN_TTY=1 WANT_WIN_CURSES=1 CROSS_TO_MSDOS=1 $IN_CI package
fi fi
condition: and(eq( variables['Agent.OS'], 'Linux' ), eq( variables.toolchain, 'cross')) condition: and(eq( variables['Agent.OS'], 'Linux' ), eq( variables.toolchain, 'cross'))
workingDirectory: $(Agent.BuildDirectory)/$(netHackPath) workingDirectory: $(Agent.BuildDirectory)/$(netHackPath)
displayName: 'Building MSDOS build' displayName: 'Building MSDOS build'
- bash: | - bash: |
sudo apt-get install texlive sudo apt install texlive texlive-latex-extra
make Guidebook make Guidebook
make Guidebook.txt make Guidebook.txt
make Guidebook.pdf make Guidebook.pdf
+2 -2
View File
@@ -157,10 +157,10 @@ des.monster({ id = "leprechaun", x=74, y=04, peaceful=0 })
des.monster({ id = "leprechaun", x=25, y=19, peaceful=0 }) des.monster({ id = "leprechaun", x=25, y=19, peaceful=0 })
des.monster({ id = "water nymph", x=25, y=18, peaceful=0 }) des.monster({ id = "water nymph", x=25, y=18, peaceful=0 })
-- Wandering the streets. -- Wandering the streets.
for i=1,4 + math.random(1 - 1,1*3) do for i = 1, math.random(4,7) do
des.monster({ id = "water nymph", coord = streets:rndcoord(1), peaceful=0 }) des.monster({ id = "water nymph", coord = streets:rndcoord(1), peaceful=0 })
des.monster({ id = "leprechaun", coord = streets:rndcoord(1), peaceful=0 }) des.monster({ id = "leprechaun", coord = streets:rndcoord(1), peaceful=0 })
end end
for i=1,7 + math.random(1 - 1,1*3) do for i = 1, math.random(7,10) do
des.monster({ id = "chameleon", coord = streets:rndcoord(1), peaceful=0 }) des.monster({ id = "chameleon", coord = streets:rndcoord(1), peaceful=0 })
end end
+2 -2
View File
@@ -35,7 +35,7 @@ des.map([[
-- chance to alter above map and turn the wings of the bottom-center into -- chance to alter above map and turn the wings of the bottom-center into
-- a pair of big (5x15) rooms -- a pair of big (5x15) rooms
for i=1,2 do for i = 1, 2 do
-- 3.6.[01]: 75% chance that both sides opened up, 25% that neither did; -- 3.6.[01]: 75% chance that both sides opened up, 25% that neither did;
-- 3.6.2: 60% twice == 36% chance that both sides open up, 24% left side -- 3.6.2: 60% twice == 36% chance that both sides open up, 24% left side
-- only, 24% right side only, 16% that neither side opens up -- only, 24% right side only, 16% that neither side opens up
@@ -58,7 +58,7 @@ for i=1,2 do
des.terrain(41,18, ".") des.terrain(41,18, ".")
end end
-- extra monsters; was [6 + 3d4] when both wings were opened up at once -- extra monsters; was [6 + 3d4] when both wings were opened up at once
for i=1,3 + math.random(2 - 1,2*3) do for j = 1, math.random(4,9) do
des.monster({ id="Angel", coord = hall:rndcoord(1), align="noalign", peaceful=0 }) des.monster({ id="Angel", coord = hall:rndcoord(1), align="noalign", peaceful=0 })
if percent(50) then if percent(50) then
des.monster({ coord = hall:rndcoord(1), peaceful=0 }) des.monster({ coord = hall:rndcoord(1), peaceful=0 })
+10 -2
View File
@@ -28,10 +28,10 @@ des.map([[
]]); ]]);
if percent(75) then if percent(80) then
local terrains = { "-", "F", "L", "T", "C" }; local terrains = { "-", "F", "L", "T", "C" };
local tidx = math.random(1, #terrains); local tidx = math.random(1, #terrains);
local choice = math.random(0, 4); local choice = math.random(0, 5);
if choice == 0 then if choice == 0 then
-- one horizontal line -- one horizontal line
des.terrain(selection.line(10,8, 65,8), terrains[tidx]); des.terrain(selection.line(10,8, 65,8), terrains[tidx]);
@@ -48,6 +48,14 @@ if percent(75) then
des.terrain(selection.rect(4,4, 70,13), terrains[tidx]); des.terrain(selection.rect(4,4, 70,13), terrains[tidx]);
local sel = selection.line(25,4, 50,4) | selection.line(25,13, 50,13); local sel = selection.line(25,4, 50,4) | selection.line(25,13, 50,13);
des.terrain(sel, '.'); des.terrain(sel, '.');
elseif choice == 4 then
-- snake
des.terrain(selection.fillrect(5,5, 69, 12), terrains[tidx]);
for i = 0, 7 do
local x = 6 + i*8;
local y = 5 + (i%2);
des.terrain(selection.fillrect(x, y, x+6, y+6), '.');
end
else else
-- nothing -- nothing
end end
+82
View File
@@ -0,0 +1,82 @@
-- NetHack bigroom bigrm-13.lua $NHDT-Date: 1652196024 2022/05/10 15:20:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.0 $
-- Copyright (c) 2026 by Pasi Kallinen
-- NetHack may be freely redistributed. See license for details.
--
-- Pillars
des.level_init({ style = "solidfill", fg = " " });
des.level_flags("mazelevel", "noflip");
des.map([[
---------------------------------------------------------------------------
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
|.........................................................................|
---------------------------------------------------------------------------
]]);
local pillar = [[
---
| |
---]];
filters = {
-- 1: all pillars
function(x, y) return true; end,
-- 2: 3 vertical lines
function(x, y) return (x%2 == 1); end,
-- 3: checkerboard
function(x, y) return (((x+y)%2) == 0); end,
-- 4: center row
function(x, y) return (y%2 == 1); end,
-- 5: top and bottom rows
function(x, y) return (y%2 == 0); end,
-- 6: random 50%
function(x, y) return (math.random(0,1) == 0); end,
-- 7: corners and center
function(x, y) return ((x/3)%2 == y%2); end,
-- 8: slanted
function(x, y) return ((x+1)//3 == y); end,
};
idx = math.random(1, #filters);
for y = 0,2 do
for x = 0,6 do
if (filters[idx](x, y)) then
des.map({ coord = {12 + x*9, 4 + y*5}, map = pillar, contents=function() end });
end
end
end
des.region(selection.area(00,00,75,18), "lit");
des.wallify();
des.non_diggable();
des.stair("up");
des.stair("down");
for i = 1,15 do
des.object();
end
for i = 1,6 do
des.trap();
end
for i = 1,28 do
des.monster();
end
+2 -2
View File
@@ -3025,7 +3025,7 @@ knight
And was a bugbear in men's eyes; And was a bugbear in men's eyes;
But had the fortune in his age But had the fortune in his age
To live a fool and die a sage. To live a fool and die a sage.
[ Don Quixote of La Mancha, by Miquel de Cervantes Saavedra ] [ Don Quixote of La Mancha, by Miguel de Cervantes Saavedra ]
~kobold ??m* ~kobold ??m*
*kobold* *kobold*
The race of kobolds are reputed to be an artificial creation The race of kobolds are reputed to be an artificial creation
@@ -3144,7 +3144,7 @@ lance
his lance into shivers, carrying him and his horse after it, his lance into shivers, carrying him and his horse after it,
and finally tumbled him a good way off from it on the field in and finally tumbled him a good way off from it on the field in
evil plight. evil plight.
[ Don Quixote of La Mancha, by Miquel de Cervantes Saavedra ] [ Don Quixote of La Mancha, by Miguel de Cervantes Saavedra ]
land mine land mine
Your heart is intact, your brain is not badly damaged, but the rest Your heart is intact, your brain is not badly damaged, but the rest
of your injuries are comparable to stepping on a land mine. You'd of your injuries are comparable to stepping on a land mine. You'd
+1 -1
View File
@@ -70,7 +70,7 @@ dungeon = {
base = 10, base = 10,
range = 3, range = 3,
chance = 40, chance = 40,
nlevels = 12 nlevels = 13
}, },
{ {
name = "medusa", name = "medusa",
+5 -3
View File
@@ -413,14 +413,16 @@ hells = {
-- 7: open cavern, "mines" with more space -- 7: open cavern, "mines" with more space
function () function ()
-- walls are either stone or lava
local wter = percent(50) and " " or "L";
des.level_init({ style = "solidfill", fg = " ", lit = 0 }); des.level_init({ style = "solidfill", fg = " ", lit = 0 });
des.level_flags("mazelevel", "noflip"); des.level_flags("mazelevel", "noflip");
des.level_init({ style="mines", fg=".", smoothed=true ,joined=true, lit=0 }); des.level_init({ style="mines", fg=".", bg = wter, smoothed=true ,joined=true, lit=0 });
local sel = selection.match("."):grow(); local sel = selection.match("."):grow();
des.terrain({ selection = sel, typ = "." }); des.terrain({ selection = sel, typ = ".", lit = 0 });
local border = selection.rect(0,0, 78, 20); local border = selection.rect(0,0, 78, 20);
des.terrain({ selection = border, typ = " " }); des.terrain({ selection = border, typ = wter, lit = 0 });
des.wallify(); des.wallify();
end, end,
+2 -2
View File
@@ -34,8 +34,8 @@ O options set options
/ what-is tell what a map symbol represents / what-is tell what a map symbol represents
\ known display list of what's been discovered \ known display list of what's been discovered
| perminv interact with persistent inventory window instead of hero+map | perminv interact with persistent inventory window instead of hero+map
v version display version number v chronicle display a list of important events
V history display game history V version display version number
^A again redo the previous command ^A again redo the previous command
^R redraw redraw the screen ^R redraw redraw the screen
^P prevmsg repeat previous message (consecutive ^P's repeat earlier ones) ^P prevmsg repeat previous message (consecutive ^P's repeat earlier ones)
+7 -5
View File
@@ -88,7 +88,7 @@ des.object({ id = "corpse", montype="watchman" })
des.object({ id = "corpse", montype="watch captain" }) des.object({ id = "corpse", montype="watch captain" })
-- Rubble! -- Rubble!
for i=1,9 + math.random(2 - 1,2*5) do for i = 1, math.random(10,19) do
if percent(90) then if percent(90) then
des.object("boulder") des.object("boulder")
end end
@@ -118,7 +118,7 @@ des.object({ id = "wand of magic missile", coord = place[5], buc="uncursed", spe
local inside = selection.floodfill(18,8) local inside = selection.floodfill(18,8)
local near_temple = selection.area(17,8, 23,14) & inside local near_temple = selection.area(17,8, 23,14) & inside
for i=1,5 + math.random(1 - 1,1*10) do for i = 1, math.random(5,15) do
if percent(50) then if percent(50) then
des.monster({ id = "orc-captain", coord = inside:rndcoord(1), peaceful=0 }); des.monster({ id = "orc-captain", coord = inside:rndcoord(1), peaceful=0 });
else else
@@ -130,12 +130,14 @@ for i=1,5 + math.random(1 - 1,1*10) do
end end
end end
-- shamans can be hanging out in/near the temple -- shamans can be hanging out in/near the temple
for i=1,math.random(2 - 1,2*3) do -- one of the shamans is higher level
des.monster({ id = "orc shaman", coord = near_temple:rndcoord(0), peaceful=0 }); for i = 1, math.random(1,6) do
des.monster({ id = "orc shaman", coord = near_temple:rndcoord(0), peaceful=0,
m_lev_adj = (i == 1) and 3 or 0 });
end end
-- these are not such a big deal -- these are not such a big deal
-- to run into outside the bars -- to run into outside the bars
for i=1,9 + math.random(2 - 1,2*5) do for i = 1, math.random(10,19) do
if percent(90) then if percent(90) then
des.monster({ id = "hill orc", peaceful = 0 }) des.monster({ id = "hill orc", peaceful = 0 })
else else
+8
View File
@@ -86,6 +86,14 @@ des.monster("gnome lord")
des.monster("dwarf") des.monster("dwarf")
des.monster("dwarf") des.monster("dwarf")
des.monster("dwarf") des.monster("dwarf")
des.monster({ id = "dwarf", peaceful = 1 })
des.monster({ id = "dwarf", peaceful = 1 })
des.monster({ id = "gnome", peaceful = 1 })
des.monster({ id = "gnome", peaceful = 1 })
des.monster({ id = "hobbit", peaceful = 1 })
des.monster({ id = "goblin", peaceful = 1 })
des.monster({ id = "kobold", peaceful = 1 })
des.monster({ id = "dog", peaceful = 1 })
des.monster({ id = "watchman", peaceful = 1 }) des.monster({ id = "watchman", peaceful = 1 })
des.monster({ id = "watchman", peaceful = 1 }) des.monster({ id = "watchman", peaceful = 1 })
des.monster({ id = "watchman", peaceful = 1 }) des.monster({ id = "watchman", peaceful = 1 })
+3
View File
@@ -48,14 +48,17 @@ nudist start your character without armor [False]
null allow nulls to be sent to your terminal [True] null allow nulls to be sent to your terminal [True]
try turning this option off (forcing NetHack to use its own try turning this option off (forcing NetHack to use its own
delay code) if moving objects seem to teleport across rooms delay code) if moving objects seem to teleport across rooms
pauper start your character with no possessions [False]
perm_invent keep inventory in a permanent window [False] perm_invent keep inventory in a permanent window [False]
pickup_stolen override pickup_types for stolen objects [True] pickup_stolen override pickup_types for stolen objects [True]
pickup_thrown override pickup_types for thrown objects [True] pickup_thrown override pickup_types for thrown objects [True]
price_quotes show remembered price quotes for unIDed items [False]
pushweapon when wielding a new weapon, put your previously [False] pushweapon when wielding a new weapon, put your previously [False]
wielded weapon into the secondary weapon slot wielded weapon into the secondary weapon slot
quick_farsight usually skip the chance to browse the map when [False] quick_farsight usually skip the chance to browse the map when [False]
randomly triggered clairvoyance takes place randomly triggered clairvoyance takes place
rawio allow the use of raw I/O [False] rawio allow the use of raw I/O [False]
reroll allow rerolling of starting inventory [False]
rest_on_space count the space bar as a rest character [False] rest_on_space count the space bar as a rest character [False]
safe_pet prevent you from (knowingly) attacking your pet(s) [True] safe_pet prevent you from (knowingly) attacking your pet(s) [True]
safe_wait require use of 'm' prefix before '.' or 's' to [True] safe_wait require use of 'm' prefix before '.' or 's' to [True]
+78
View File
@@ -895,4 +895,82 @@ start: Enhanced1
G_trwall_mines: U+251C/113-126-142 G_trwall_mines: U+251C/113-126-142
finish finish
start: AmigaFont
Description: Amiga hack.font line-drawing and effect characters
# Dungeon features
S_stone: \x20
S_vwall: \xc0
S_hwall: \xc1
S_tlcorn: \xc2
S_trcorn: \xc3
S_blcorn: \xc4
S_brcorn: \xc5
S_crwall: \xc6
S_tuwall: \xd8
S_tdwall: \xd6
S_tlwall: \xd7
S_trwall: \xd5
S_ndoor: \xd9
S_vodoor: \x91
S_hodoor: \x92
S_vcdoor: \x93
S_hcdoor: \x94
S_bars: '#'
S_tree: '#'
S_room: '.'
S_darkroom: \x20
S_corr: \xe5
S_litcorr: \xe5
S_upstair: '<'
S_dnstair: '>'
S_upladder: '<'
S_dnladder: '>'
S_altar: '_'
S_grave: \x5c
S_throne: '#'
S_sink: '{'
S_fountain: '}'
S_pool: '*'
S_ice: '}'
S_lava: '*'
S_vodbridge: '*'
S_hodbridge: '#'
S_vcdbridge: '#'
S_hcdbridge: '.'
S_air: '#'
S_cloud: '}'
# Traps: all default to '^' except web
S_web: '"'
# Effects
S_vbeam: \xf1
S_hbeam: \xf0
S_lslant: \xf2
S_rslant: \xf3
S_digbeam: '*'
S_flashbeam: '!'
S_boomleft: '{'
S_boomright: '}'
S_ss1: '@'
S_ss2: '&'
S_ss3: '*'
S_ss4: '#'
S_sw_tl: \xf4
S_sw_tc: \xf5
S_sw_tr: \xf6
S_sw_ml: \xf7
S_sw_mr: \xef
S_sw_bl: \xf8
S_sw_bc: \xf9
S_sw_br: \xfa
S_explode1: \xe6
S_explode2: \xea
S_explode3: \xe7
S_explode4: \xec
S_explode5: \xd4
S_explode6: \xed
S_explode7: \xe8
S_explode8: \xeb
S_explode9: \xe9
finish
# symbols EOF # symbols EOF
+1
View File
@@ -30,6 +30,7 @@ Debug-Mode Quick Reference:
#wizloadlua == load and execute a lua script #wizloadlua == load and execute a lua script
#wizmakemap == recreate the current dungeon level #wizmakemap == recreate the current dungeon level
#wizmondiff == [Opt] check for discrepancies in monster difficulty ratings #wizmondiff == [Opt] check for discrepancies in monster difficulty ratings
#wizobjprobs == [Opt] list actual probabilities of item generation
#wizrumorcheck == validate rumor indexing; also show first, second, and last #wizrumorcheck == validate rumor indexing; also show first, second, and last
random engravings, epitaphs, and hallucinatory monsters random engravings, epitaphs, and hallucinatory monsters
#wizseenv == show map locations' seen vectors #wizseenv == show map locations' seen vectors
+130 -14
View File
@@ -1,4 +1,4 @@
.\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.598 $ $NHDT-Date: 1745139202 2025/04/20 00:53:22 $ .\" $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.614 $ $NHDT-Date: 1770881338 2026/02/11 23:28:58 $
.\" .\"
.\" This is an excerpt from the 'roff' man page from the 'groff' package. .\" This is an excerpt from the 'roff' man page from the 'groff' package.
.\"+-- .\"+--
@@ -31,8 +31,21 @@
.lt 70n .lt 70n
.\} .\}
. .
.so tmac.nh \" extra macros which aren't in tmac.n .\" Load extra macros that "tmac.n" doesn't define.
.if !\n(nH .so doc/tmac.nh .de So
.ie \n(.g&(\n(.x=1)&(\n(.y>22) .soquiet \\$1
.el .so \\$1
..
.
.So tmac.nh
.if !\n(nH So doc/tmac.nh
.
.if !\n(nH \{\
.tm fatal error: cannot locate "tmac.nh" macro package
.ab
.\}
.
.rm So
. .
.\" building Guidebook.txt doesn't have CR font available; groff 1.23 issues .\" building Guidebook.txt doesn't have CR font available; groff 1.23 issues
.\" a warning each time any font can't be loaded; earlier versions silently .\" a warning each time any font can't be loaded; earlier versions silently
@@ -47,7 +60,7 @@
.ds f0 \*(vr .ds f0 \*(vr
.ds f1 \" empty .ds f1 \" empty
.\"DO NOT REMOVE NH_DATESUB .ds f2 Date(%B %-d, %Y) .\"DO NOT REMOVE NH_DATESUB .ds f2 Date(%B %-d, %Y)
.ds f2 May 1, 2025 .ds f2 March 25, 2026
. .
.\" A note on some special characters: .\" A note on some special characters:
.\" \(lq = left double quote .\" \(lq = left double quote
@@ -131,7 +144,8 @@ will vary with your background and training:
.pg .pg
\fIArcheologists\fP understand dungeons pretty well; this enables them \fIArcheologists\fP understand dungeons pretty well; this enables them
to move quickly and sneak up on the local nasties. They start equipped to move quickly and sneak up on the local nasties. They start equipped
with the tools for a proper scientific expedition. with the tools for a proper scientific expedition, and are able to read
ancient languages.
.pg .pg
\fIBarbarians\fP are warriors out of the hinterland, hardened to battle. \fIBarbarians\fP are warriors out of the hinterland, hardened to battle.
They begin their quests with naught but uncommon strength, a trusty hauberk, They begin their quests with naught but uncommon strength, a trusty hauberk,
@@ -1233,6 +1247,9 @@ Autocompletes.
Default key is \(oqM-A\(cq, and also \(oq\(haN\(cq if Default key is \(oqM-A\(cq, and also \(oq\(haN\(cq if
.op number_pad .op number_pad
is on. is on.
.lp ""
Preceding #annotate with the \(oqm\(cq prefix is the same as
#overview with the prefix.
.lp "#apply " .lp "#apply "
Apply (use) a tool such as a pick-axe, a key, or a lamp. Apply (use) a tool such as a pick-axe, a key, or a lamp.
Default key is \(oqa\(cq. Default key is \(oqa\(cq.
@@ -1268,6 +1285,7 @@ Talk to someone.
Default key is \(oqM-c\(cq. Default key is \(oqM-c\(cq.
.lp "#chronicle" .lp "#chronicle"
Show a list of important game events. Show a list of important game events.
Default key is \(oqv\(cq.
.lp "#close " .lp "#close "
Close a door. Close a door.
Default key is \(oqc\(cq. Default key is \(oqc\(cq.
@@ -1368,7 +1386,6 @@ option is On, clicking on the hero (or steed when mounted) will
execute this command. execute this command.
.lp "#history " .lp "#history "
Show long version and game history. Show long version and game history.
Default key is \(oqV\(cq.
.lp #inventory .lp #inventory
Show your inventory. Show your inventory.
Default key is \(oqi\(cq. Default key is \(oqi\(cq.
@@ -1740,6 +1757,18 @@ floor container menu.
.lp "" .lp ""
Autocompletes. Autocompletes.
Default key is \(oqM-T\(cq. Default key is \(oqM-T\(cq.
.lp "#toggle "
Toggle a boolean option on or off.
Requires a parameter in parenthesis, the name of the option to toggle.
The option must be settable in-game.
.lp ""
For example:
.sd
.ft CR
BIND=':toggle(price_quotes)
BIND=@:toggle(autopickup)
.ft
.ed
.lp "#travel " .lp "#travel "
Travel to a specific location on the map. Travel to a specific location on the map.
Default key is \(oq_\(cq. \" underscore Default key is \(oq_\(cq. \" underscore
@@ -1809,7 +1838,7 @@ Default key is \(oqM-v\(cq.
.lp #versionshort .lp #versionshort
Show the program's version number, plus the date and time that the Show the program's version number, plus the date and time that the
running copy was built from sources (not the version's release date). running copy was built from sources (not the version's release date).
Default key is \(oqv\(cq. Default key is \(oqV\(cq.
.lp "#vision " .lp "#vision "
Show vision array. Show vision array.
Autocompletes. Autocompletes.
@@ -1909,6 +1938,7 @@ Wish for something.
Autocompletes. Autocompletes.
Debug mode only. Debug mode only.
Default key is \(oq\(haW\(cq. Default key is \(oq\(haW\(cq.
Precede this command with the \(oq\f(CRm\fP\(cq prefix to show a wish history menu.
.lp "#wmode " .lp "#wmode "
Show wall modes. Show wall modes.
Autocompletes. Autocompletes.
@@ -2581,6 +2611,56 @@ Sometimes the bless or curse state of objects is referred to as their
or \(lq\f(CRBUCX\fP\(rq for Blessed, Uncursed, Cursed, or unknown. or \(lq\f(CRBUCX\fP\(rq for Blessed, Uncursed, Cursed, or unknown.
(The term \fIbeatitude\fP is occasionally used as well.) (The term \fIbeatitude\fP is occasionally used as well.)
.hn 2 .hn 2
Artifacts
.pg
Some objects have been imbued with special powers and are known as
\fBArtifacts\fP.
They have specific types (such as long sword or orcish dagger) and distinct
names such as \fIGiantslayer\fP or \fIGrimtooth\fP.
Artifact weapons typically do more damage than their ordinary counterparts.
Some do extra damage against all monsters, others only against specific
types of monsters so aren't better than regular weapons against other types.
Some confer defensive capabilities when wielded or have other powers that
aren't listed here.
.pg
You might find them simply lying on the floor, including but not limited
to inside shops, or be granted as a reward for \(lq#offer\(rq on an
altar to your patron deity.
A few might be dropped by monsters, or might be converted from an ordinary
object of the same type via assigning the right name.
.\" should we mention dipping for Excalibur here?
Or you might wish for them, if you happen to be granted a wish, but such
wishes can fail.
.pg
Some artifacts have a specific alignment, others don't.
You won't obtain aligned ones that have a different alignment from yours
via offering and might get a shock if you attempt to wish for any of those
or find one and attempt to use it.
.pg
Each role has a distinct artifact that is contained in the \fIQuest\fP
dungeon branch.
These are commonly known as quest artifacts.
All are aligned and most are non-weapons.
They won't be found randomly.
.pg
The \(oq\f(CR\\\fP\(cq and \(oq\f(CR\`a\fP\(cq commands will
list artifacts that you have fully identified (knowing the name and item
type isn't sufficient).
.hn 2
Relics
.pg
There are three unique items that are named and have limited special
powers but aren't classified as artifacts.
Each is guarded by a particular monster and you'll need to collect all
three for use late in the game.
.\" The relics are listed in the same order as the Oracle's message about
.\" them rather than in the order they need to be used for the invocation.
They are \fIthe Bell of Opening\fP,
\fIthe Book of the Dead\fP, and
\fIthe Candelabrum of Invocation\fP.
Their corresponding descriptions when not yet identified are
silver bell, papyrus spellbook, and candelabrum.
.hn 2
Weapons (\(oq)\(cq) Weapons (\(oq)\(cq)
.pg .pg
Given a chance, most monsters in the Mazes of Menace will gratuitously try to Given a chance, most monsters in the Mazes of Menace will gratuitously try to
@@ -2925,7 +3005,7 @@ Some objects of subtle enchantment are difficult to identify without these.
.pg .pg
A scroll whose label is known can be read even when the hero is blind. A scroll whose label is known can be read even when the hero is blind.
If a scroll has been discovered, it will be listed in inventory by type If a scroll has been discovered, it will be listed in inventory by type
rather than by label, but the label is known in that situtaion even though rather than by label, but the label is known in that situation even though
it isn't shown. it isn't shown.
.pg .pg
Many scrolls produce a different effect from usual if they are blessed or Many scrolls produce a different effect from usual if they are blessed or
@@ -3322,6 +3402,14 @@ not penalized for being spoken to by an angry god, priest(ess), or
other religious figure; a true atheist would hear the words but other religious figure; a true atheist would hear the words but
attach no special meaning to them. attach no special meaning to them.
.pg .pg
A pauper starts the game with no possessions, no spells, and no weapon or
spell skills (and if playing as a knight, your pony will not have a saddle).
Can only be initiated by starting a new game with \f(CROPTIONS=pauper\fP
set in your run-time configurtion file or \f(CRNETHACKOPTIONS\fP environment
variable.
Once the game is underway, you can acquire and use items, spells, and skills
in the usual way.
.pg
Most players fight with a wielded weapon (or tool intended to be Most players fight with a wielded weapon (or tool intended to be
wielded as a weapon). Another challenge is to win the game without wielded as a weapon). Another challenge is to win the game without
using such a wielded weapon. You are still permitted to throw, using such a wielded weapon. You are still permitted to throw,
@@ -3478,7 +3566,8 @@ the Castle level's drawbridge or can be given to you via prayer boon.
and \fIPauper\fP are also conducts, and they can only be and \fIPauper\fP are also conducts, and they can only be
enabled by setting the correspondingly named option in NETHACKOPTIONS enabled by setting the correspondingly named option in NETHACKOPTIONS
or run-time configuration file prior to game start. or run-time configuration file prior to game start.
In the case of \fIBlind\fP and \fIDeaf\fP, the option also enforces the conduct. In the case of \fIBlind\fP and \fIDeaf\fP, the option also enforces the
conduct.
They aren't really significant accomplishments unless/until you make They aren't really significant accomplishments unless/until you make
substantial progress into the dungeon. substantial progress into the dungeon.
. .
@@ -3536,7 +3625,7 @@ is a section marker (the closing \(oq\f(CR]\fP\(cq can be followed
by whitespace and then an arbitrary comment beginning with \(oq\f(CR#\fP\(cq). by whitespace and then an arbitrary comment beginning with \(oq\f(CR#\fP\(cq).
The text between the square brackets is the section name. The text between the square brackets is the section name.
Section markers are only valid after a CHOOSE directive and their names Section markers are only valid after a CHOOSE directive and their names
are case insensitive. are case-insensitive.
Lines after a section marker belong to that section up until another Lines after a section marker belong to that section up until another
section starts or a marker without a name is encountered or the file ends. section starts or a marker without a name is encountered or the file ends.
Lines within sections are ignored unless a CHOOSE directive has selected Lines within sections are ignored unless a CHOOSE directive has selected
@@ -3664,13 +3753,14 @@ See the \(lqModifying NetHack Symbols\(rq section.
Example: Example:
.sd .sd
\f(CR# replace small punctuation (tick marks) with digits\fP \f(CR# replace small punctuation (tick marks) with digits\fP
\f(CRSYMBOLS=S_boulder:0,S_golem:7\fP \f(CRSYMBOLS=S_golem:7\fP
.ed .ed
.lp WIZKIT .lp WIZKIT
Debug mode only: extra items to add to initial inventory. Debug mode only: extra items to add to initial inventory.
Value is the name of a text file containing a list of item names, Value is the name of a text file containing a list of item names,
one per line, up to a maximum of 128 lines. one per line, up to a maximum of 128 lines.
Each line is processed by the function that handles wishing. Each line is processed by the function that handles wishing.
Entries are added to the wish history; see the wizwish-command.
.lp "" .lp ""
Example: Example:
.sd .sd
@@ -3699,7 +3789,8 @@ OPTIONS=color # Display things in color if possible
OPTIONS=lit_corridor # Show lit corridors differently OPTIONS=lit_corridor # Show lit corridors differently
OPTIONS=hilite_pet,hilite_pile OPTIONS=hilite_pet,hilite_pile
# Replace small punctuation (tick marks) with digits # Replace small punctuation (tick marks) with digits
SYMBOLS=S_boulder:0,S_golem:7 OPTIONS=boulder:0
SYMBOLS=S_golem:7
# #
# No startup splash screen. Windows GUI only. # No startup splash screen. Windows GUI only.
OPTIONS=!splash_screen OPTIONS=!splash_screen
@@ -4409,6 +4500,10 @@ The positive (no \(oq!\(cq) and negative (with \(oq!\(cq) entries
can be intermixed. can be intermixed.
.lp pauper .lp pauper
Start the character with no possessions (default false). Persistent. Start the character with no possessions (default false). Persistent.
.lp ""
Also start with no spells or skills, which are tied to starting equipment.
Does not inhibit acquiring and using items, spells, and skills once play
has started.
.lp perm_invent .lp perm_invent
If true, always display your current inventory in a window (default false). If true, always display your current inventory in a window (default false).
.lp "" .lp ""
@@ -4527,6 +4622,15 @@ user name (on multi-user systems) or specifying a particular character
name (on single-user systems) or it might be disabled entirely. Requesting name (on single-user systems) or it might be disabled entirely. Requesting
it when not allowed or not possible results in explore mode instead. it when not allowed or not possible results in explore mode instead.
Default is normal play. Default is normal play.
.lp price_quotes
Whenever the game mentions the name of an object you haven't identified yet,
it also mentions the range of buy and sell prices you have seen for that
item (to help narrow down what it could be).
The price shown is the unit price for one item (even when you are looking at
a stack of multiple items).
Many players may want to turn this on while identifying objects, and then
turn it back off again for general play.
Default is off.
.lp pushweapon .lp pushweapon
Using the \(oqw\(cq (wield) command when already wielding Using the \(oqw\(cq (wield) command when already wielding
something pushes the old item into your alternate weapon slot (default off). something pushes the old item into your alternate weapon slot (default off).
@@ -4555,6 +4659,16 @@ If \f(CRrace\fP is not specified, there is no default value;
player will be prompted unless role forces a choice for race. player will be prompted unless role forces a choice for race.
Cannot be set with the \(oq\f(CRO\fP\(cq command. Cannot be set with the \(oq\f(CRO\fP\(cq command.
Persistent. Persistent.
.lp reroll
Allows rerolling your character's starting inventory and attributes (default
false). Persistent.
.lp ""
Note that rerolling your character is not a recommended way to play if aiming
merely to win (a lucky start has a much smaller influence on whether or not
you win the game than your actions later in the game). This option exists
partly as an acknowledgement that some players will insist on doing so anyway,
and partly because rerolling may be necessary for certain types of challenge
games.
.lp rest_on_space .lp rest_on_space
Make the space bar a synonym for the \(oq.\(cq (#wait) command (default off). Make the space bar a synonym for the \(oq.\(cq (#wait) command (default off).
Persistent. Persistent.
@@ -4659,7 +4773,7 @@ or you are making screenshots or streaming video.
Using the Using the
.op statuslines:3 .op statuslines:3
option is recommended so that there will be more room available for option is recommended so that there will be more room available for
status information, unless you're using nethack's \fIQt\fP interface status information, unless you're using NetHack's \fIQt\fP interface
or your terminal emulator window displays fewer than 25 lines. or your terminal emulator window displays fewer than 25 lines.
Persistent. Persistent.
.lp "silent " .lp "silent "
@@ -5552,7 +5666,9 @@ change the color or appearance of fields in the status display.
.pg .pg
The format for defining status colors is: The format for defining status colors is:
.SD n .SD n
\f(CROPTION=hilite_status:\fIfield-name\fP/\fIbehavior\fP/\fIcolor\fP&\fIattributes\fP\fP .\" was "\f(CR...\fI...\fP\fP" but font changes don't nest so final \fP didn't
.\" restore the pre-\f(CR font; assume that was Roman and explicitly use \fR
\f(CROPTION=hilite_status:\fIfield-name\fP/\fIbehavior\fP/\fIcolor\fP&\fIattributes\fP\fR
.ED .ED
.pg .pg
For example, the following line in your configuration file will cause For example, the following line in your configuration file will cause
+2345 -2280
View File
File diff suppressed because it is too large Load Diff
+1674 -1608
View File
File diff suppressed because it is too large Load Diff
+36 -34
View File
@@ -6,47 +6,47 @@ NAME
dlb - NetHack data librarian dlb - NetHack data librarian
SYNOPSIS SYNOPSIS
dlb { xct } [ vfIC ] arguments... [ files... ] dlb {c|t|x}[v][C directory] [file] ...
dlb {c|t|x}[v]I list-file
dlb {c|t|x}[v][f archive-file-name] [file] ...
DESCRIPTION DESCRIPTION
Dlb is a file archiving tool in the spirit (and tradition) of tar for Dlb is a file archiving tool in the spirit (and tradition) of tar(1)
NetHack version 3.1 and higher. It is used to maintain the archive for nethack(6) version 3.1 and higher. It is used to maintain the
files from which NetHack reads special level files and other read-only archive files from which the game reads special level files and other
information. Note that like tar the command and option specifiers are read-only information. Note that like tar, the letters specifying the
specified as a continuous string and are followed by any arguments operation and options are expressed as a continuous string. Unlike
required in the same order as the option specifiers. tar, dlb is configured with a default set of file names to process.
This facility is optional and may be excluded during NetHack configura- Operations
tion. c causes dlb to create a new archive from files in the current direc-
tory.
COMMANDS t lists the files in the archive.
The x command causes dlb to extract the contents of the archive into
the current directory.
The c command causes dlb to create a new archive from files in the cur- x causes dlb to extract the contents of the archive into the current
rent directory. directory.
The t command lists the files in the archive. OPTIONS
C dir Change directory to dir before trying to read any files.
OPTIONS AND ARGUMENTS f archive Read from or write to archive instead of LIBFILE (usually
v verbose output the nhdat file in the playground).
f archive specify the archive. Default if f not specified is LIBFILE I list-file Read from list-file the names of files to emplace within
(usually the nhdat file in the playground). or extract from the archive. The default for archive cre-
ation is LIBLISTFILE.
I lfile specify the file containing the list of files to put in to v Operate verbosely.
or extract from the archive if no files are listed on the command line.
Default for archive creation if no files are listed is LIBLISTFILE.
C dir change directory. Changes directory before trying to read
any files (including the archive and the lfile).
EXAMPLES EXAMPLES
Create the default archive from the default file list: Create the default archive from the default file list:
dlb c dlb c
List the contents of the archive 'foo': List the contents of the archive foo:
dlb tf foo dlb tf foo
AUTHOR AUTHOR
Kenneth Lorber Kenneth Lorber
@@ -55,15 +55,17 @@ SEE ALSO
nethack(6), tar(1) nethack(6), tar(1)
BUGS BUGS
Not a good tar emulation; - does not mean stdin or stdout. Should o Not a good tar emulation; - does not mean stdin or stdout.
include an optional compression facility. Not all read-only files for
NetHack can be read out of an archive; examining the source is the only o Should include an optional compression facility.
way to know which files can be.
o Not all read-only files for NetHack can be read out of an archive;
examining the source is the only way to know which files can be.
COPYRIGHT COPYRIGHT
This file is Copyright (C) Kenneth Lorber, 2024 for version keni-git- This file is Copyright (C) Kenneth Lorber, 2024 for version keni-git-
set:1.13. NetHack may be freely redistributed. See license for set:1.13. NetHack may be freely redistributed. See license for de-
details. tails.
+30 -4
View File
@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.0 $ $NHDT-Date: 1676619775 2023/02/17 07:42:55 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.21 $ $NHDT-Date: 1683746783 2023/05/10 19:26:23 $
fixes36.7 contains a summary of changes made to 3.6.6 in order to fixes36.7 contains a summary of changes made to 3.6.6 in order to
produce 3.6.7 as well as any post-release fixes in binaries. produce 3.6.7 as well as any post-release fixes in binaries.
@@ -40,6 +40,32 @@ none
Fixes to 3.6.7 Post-release Problems and other Post-release changes Fixes to 3.6.7 Post-release Problems and other Post-release changes
------------------------------------------------------------------- -------------------------------------------------------------------
none extend the fix for build failure w/ newer C library headers to macOS (pr #988)
Windows: fix range error detected by address sanitizer in plselInitDialog()
Windows: nethackw.exe was vertically spacing out menu items based on
the height of the tileset in use, even though the tiles in the
menu were drawn at the default height of 16 anyway; get rid of
the extraneous vertical spacing between the menu rows
hilite_pile can remain on the map after eating food off the floor
vms: update winprocs.h to ensure that CLR_MAX is defined; necessary for
compiling vmsmail.c which uses winprocs.h but not hack.h
curses: when #quitting, just before the high scores are about to be shown
status_window was NULL and dereferenced, so add checks (issue #1090)
unix: update Makefile.dat so that if parallel make is used, it will build
the data files "engrave", "epitaph", and "bogusmon" sequentially;
'makedefs -s' builds all three at once and doing parallel instances
of that can produce seemingly mysterious problems by stomping on
each other's results
fix the mingw32 build of NetHack 3.6.7 by updating sys/winnt/Makefile.gcc,
sys/winnt/winnt.c and sys/winnt/stubs.c
correct the Ixoth tile
makedefs can produce individual bogusmon, engrave and epitaph files
drinkfountain() fate 24 to curse objects could end up cursing objects
on the floor chain instead of the intended inventory object chain
proceed with showpaths option even if the sysconf file is missing
avoid memory leak in mk_artifact(); cherry-pick of 3cca4f27 from 3.7 WIP
avoid using col in Guidebook build, since some distros no longer include
it, particularly some that use musl libc
back-port some nroff macro updates for Guidebook
prevent a crash when using 'O' to interactively set a text match highlight
for hunger
+133 -17
View File
@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1535 $ $NHDT-Date: 1740629713 2025/02/26 20:15:13 $ NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1614 $ $NHDT-Date: 1769342601 2026/01/25 04:03:21 $
General Fixes and Modified Features General Fixes and Modified Features
----------------------------------- -----------------------------------
@@ -215,7 +215,7 @@ if riding or levitating, hero could apply bullwhip downward to pull up things
some monster code was checking whether pets or engulfers were eating green some monster code was checking whether pets or engulfers were eating green
slime by checking for green slime corpse instead of glob slime by checking for green slime corpse instead of glob
change light radius of stack of candles to square root change light radius of stack of candles to square root
could get redundate "mon hits other-mon" messages when mon wields an artifact could get redundant "mon hits other-mon" messages when mon wields an artifact
failed untrap while mounted that moved hero onto the trap would leave steed failed untrap while mounted that moved hero onto the trap would leave steed
with stale coordinates, triggering warnings if 'sanity_check' is On with stale coordinates, triggering warnings if 'sanity_check' is On
when digging a pit results in it being filled by adjacent pool or lava, any when digging a pit results in it being filled by adjacent pool or lava, any
@@ -530,7 +530,7 @@ innocuous items like scrolls or eucalyptus leaves did harm when falling on
hero's head after being thrown upward hero's head after being thrown upward
fighter types who start out knowing all non-magic armor should not know fighter types who start out knowing all non-magic armor should not know
cornuthaum and dunce cap cornuthaum and dunce cap
prediscovered weapons adjustmens: only knights and samurai know polearms; prediscovered weapons adjustments: only knights and samurai know polearms;
rangers know launchers (bows), ammo (arrows), and spears regardless rangers know launchers (bows), ammo (arrows), and spears regardless
of their race/species; likewise, rogues know all daggers of their race/species; likewise, rogues know all daggers
if the move counter ever reaches 1000000000, end the game if the move counter ever reaches 1000000000, end the game
@@ -715,7 +715,7 @@ selection of random engravings, epitaphs, and hallucinatory monster names had
follow longer than average lines are most likely to be chosen and follow longer than average lines are most likely to be chosen and
ones which follow shorter than average lines are least likely; use ones which follow shorter than average lines are least likely; use
same workaround as for rumors: pad the shortest lines; result isn't same workaround as for rumors: pad the shortest lines; result isn't
uniforn distribution but is better (tradeoff vs size; see makedefs) uniform distribution but is better (tradeoff vs size; see makedefs)
make selection of random rumors, engravings, epitaphs, and hallucinatory monst make selection of random rumors, engravings, epitaphs, and hallucinatory monst
names have uniform distribution by handling long lines specially names have uniform distribution by handling long lines specially
when filling a special room with monsters, if one that can come in groups got when filling a special room with monsters, if one that can come in groups got
@@ -837,7 +837,8 @@ if a lit potion of oil on the floor was launched by an explosion and it hit
it could trigger an "obj_is_local" panic when end of game cleanup it could trigger an "obj_is_local" panic when end of game cleanup
tried to extinguish it as a light source tried to extinguish it as a light source
place_object() validated coordinates after using them to index level.objects place_object() validated coordinates after using them to index level.objects
killed rope golem may drop leashes and bullwhips killed rope golem may drop leashes, bullwhips, and grappling hooks
killed leather golem may drop leather cloaks, and saddles
using magic portals stuns hero for a few turns using magic portals stuns hero for a few turns
using level teleporters confuses hero without teleport control for a few turns using level teleporters confuses hero without teleport control for a few turns
clear obj->bypass for buried objects [a giant on ice triggers a fire trap, clear obj->bypass for buried objects [a giant on ice triggers a fire trap,
@@ -1237,7 +1238,7 @@ restore the ability for trap creation via magic which creates pits to destroy
allow #sit while flying over a squeaky board trap to trigger it allow #sit while flying over a squeaky board trap to trigger it
weight of statues of wraiths and of monsters which never leave a corpse was 0 weight of statues of wraiths and of monsters which never leave a corpse was 0
when a werecreature in human form attacked hero, it could transform to critter when a werecreature in human form attacked hero, it could transform to critter
despite hero having the Protection_from_shape_changers_attibute despite hero having the Protection_from_shape_changers_attribute
status highlighting for hit points didn't work as intended for up or down HP status highlighting for hit points didn't work as intended for up or down HP
changes; 'up' rule was used for both, 'down' rule was ignored changes; 'up' rule was used for both, 'down' rule was ignored
unhide an unseen water monster using a polymorph trap on land unhide an unseen water monster using a polymorph trap on land
@@ -1510,6 +1511,7 @@ if a tree and a boulder or statue were at the same location, applying an axe
would break the boulder or statue rather than chop the tree would break the boulder or statue rather than chop the tree
avoid premapping outside Sokoban map to prevent showing stone glyphs avoid premapping outside Sokoban map to prevent showing stone glyphs
Grimtooth is permanently poisoned, protects from poison, and can fling poison Grimtooth is permanently poisoned, protects from poison, and can fling poison
invoke cost for Grimtooth and Sunsword can be paid with magic power
cursed magic whistle can teleport you to your pet cursed magic whistle can teleport you to your pet
Fire and Frost Brand can be invoked for expert level fireball or cone of cold Fire and Frost Brand can be invoked for expert level fireball or cone of cold
wielding Trollsbane grants hungerless regeneration wielding Trollsbane grants hungerless regeneration
@@ -1528,6 +1530,72 @@ a gas spore that was killed when an engulfer swallowed it produced an explosion
hallucination can display objects on the map that have a description (for hallucination can display objects on the map that have a description (for
shuffling into play at game start) but no name; examining those might shuffling into play at game start) but no name; examining those might
trigger a crash trigger a crash
some food and paper items do no damage when bashing
improved messages for oilskin sacks protecting from water damage
some messages by amorous demons and mail daemon were delivered as verbal ones
even when the hero is deaf
travel couldn't find the vibrating square if it was covered by an object or
a monster; it isn't really a trap so treat it as special terrain
travel would stop one step in front of known vibrating square like other traps
fix bug which delayed burden changes due to monster actions (e.g. reverting to
natural form due to damage, changing carry capacity) for one turn
on arboreal levels (Ranger quest) where STONE terrain is treated as TREE, an
object at a tree location would be described as "embedded in stone"
an item at an ordinary tree location, whether the level is arboreal or not,
would be described as itself with no mention of the tree
some types of shopkeeper now start with a scroll of charging
objects are now accurately tracked as discovered even if not type-named nor
formally identified (fixing some bugs in scroll writing, and making
the discoveries list more accurate)
you cannot sacrifice objects/corpses while stunned or confused
'whatis' actions // and /? didn't work when the lootabc option was on, they
required /a and /c instead; add '/' and '?' as group accelerators so
that they work; /y and /n for them now only work when lootabc is off
writing on an unidentified scroll of blank paper identifies blank paper
dumplogs include spells and skills
praying will not restore monster-form HP while polymorphed, unless you
have unchanging
winter wolf cub was missing for monster to lycanthrope conversion
monster elves shooting arrows weren't getting intended small to-hit and damage
bonuses
luck has a reduced effect on to-hit chance
monsters use wand of teleportation to move hero away from item pile
lycanthrope instincts keep hero from changing shape while next to hostiles
scroll of enchant armor formula has changed (in particular, magical armor now
gains less enchantment when enchanted than nonmagical armor and
uncursed scrolls can sometimes enchant by more than one point)
dragonhide can rot
throwing ammo without a launcher produces a message
polymorphing into a large polyform unequips rather than destroying cloaks
clarify in the #quit message that it doesn't save the game
cursed potion of invisibility removes intrinsic invisibility
fix bug which caused engulf damage from air elementals and fog clouds to
ignore damage reduction from armor class
elementals do double damage on their home plane
water elementals move slightly more slowly
the "totally digested" instadeath timer is much faster
slow monster effects are more effective against faster enemies
light-spell is clerical, if playing a priest
boomerang can hit multiple monsters
the "bustling town" minetown has more peacefuls
healers may get tiny damage increase when attacking with knives
allow rogues to also backstab sleeping or paralyzed monsters
rogues cannot backstab monsters that have no backside
give experience if opening Schroedinger's Box causes death of the cat inside
priest donation amounts are explicitly stated, randomized slightly, based on
peak rather than current level, and allow for bulk donations (buying
larger amounts of clairvoyance/protection) if you have a lot of gold
amulet of magical breathing increases power regeneration
change some command keys, 'v' is now chronicle, 'V' is versionshort,
m-prefix 'V' is longer version, remove key binding of #history
one orc-town shaman has a higher level, affecting spellcasting
hero has a small chance of catching items thrown at them
wizard mode: history menu for #wizwish and WIZKIT
monster priests and wizards did not cast spells
prevent phaseable monsters hiding deep inside nondiggable walls
blessed potion of see invisible does not guarantee the intrinsic
prevent selecting all options in #optionsfull menu
shapeshifters change shape less
Fixes to 3.7.0-x General Problems Exposed Via git Repository Fixes to 3.7.0-x General Problems Exposed Via git Repository
@@ -1855,7 +1923,7 @@ after the fix for zombie reviving near hero (which now interrupts hero's
occupation), could get "revive panic" when eating a troll corpse if occupation), could get "revive panic" when eating a troll corpse if
it revived on the same turn that eating the corpse would finish it revived on the same turn that eating the corpse would finish
a wizard's starting equipment was supposed to include a random spellbook of a wizard's starting equipment was supposed to include a random spellbook of
spell level 1 through 3 but it was being foced to be level 1 spell level 1 through 3 but it was being forced to be level 1
earlier fix for prices of unpaid objects going away in persistent inventory earlier fix for prices of unpaid objects going away in persistent inventory
display when hero bought something during itemized billing didn't work display when hero bought something during itemized billing didn't work
if paying for a used-up shop item--prices of any unpaid items vanished if paying for a used-up shop item--prices of any unpaid items vanished
@@ -1945,7 +2013,7 @@ don't blame/credit hero for stinking cloud if dying quest nemesis releases one
Lua selection operations 'subtract' and 'xor' didn't always work as intended Lua selection operations 'subtract' and 'xor' didn't always work as intended
accept 'true' or 'false' as value for des.object field 'trapped' accept 'true' or 'false' as value for des.object field 'trapped'
special level loader didn't check for bad coordinates supplied by <level>.lua special level loader didn't check for bad coordinates supplied by <level>.lua
file thorougnly enough file thoroughly enough
hero might not be credited with "entered Mine Town" achievement for the town hero might not be credited with "entered Mine Town" achievement for the town
variations which treat the whole level as the town if that level gets variations which treat the whole level as the town if that level gets
entered via falling or level teleport entered via falling or level teleport
@@ -2069,7 +2137,7 @@ restoring a save file could trigger impossible "rnd(0) attempted" if it tried
a released version, it would crash due to divide by 0 error instead a released version, it would crash due to divide by 0 error instead
fix regression of a post-3.6 fix: if 2 Wizards of Yendor were in play and 1 fix regression of a post-3.6 fix: if 2 Wizards of Yendor were in play and 1
escaped the dungeon, bookkeeping for current number of Wizards stayed escaped the dungeon, bookkeeping for current number of Wizards stayed
at 2, interferring with future Wizard behavior at 2, interfering with future Wizard behavior
sometimes a repeat count from the preceding command carried over to most sometimes a repeat count from the preceding command carried over to most
recent one when using do-again (^A); if the most recent one was an recent one when using do-again (^A); if the most recent one was an
extended command, the spurious repeat was for '#' extended command, the spurious repeat was for '#'
@@ -2128,6 +2196,36 @@ successfully disarming a chest trap was clearing the chest's 'tknown' bit
when game ended with 'force_invmenu' On, final disclosure of inventory would when game ended with 'force_invmenu' On, final disclosure of inventory would
contain spurious menu entry "? - (list likely candidates)" contain spurious menu entry "? - (list likely candidates)"
avoid reporting "a gold pieces appears next to you" for mimic avoid reporting "a gold pieces appears next to you" for mimic
don't try to split a pudding that got jousted into a hole and is off the map
mounted hero was able to deliver joust hits when trapped
timer sanity check for melting ice gave false complaint about non-ice for
frozen moat under open drawbridge
mhitm_ad_phys() was not applying Half_physical_damage when hero was target
throwing crystal plate mail or helm of brilliance up against the ceiling could
result in the item being cracked and then vanishing
yn_function (used all over the place) sometimes triggered an impossible()
during do-again (^A) processing [ongoing revisions; more are probably
needed; listed here in case ^A behavior changes]
uncursed genocide while hallucinating deliberately mis-reports hero's role as
target but was also inappropriately showing it to livelog/#chronicle
livelog/#chronicle for bribing a demon lord reported random monster and
currency if hero was hallucinating
livelog/#chronicle for saving-grace: if saving-grace prevents hero's death,
report it [at present, it uses the livelog classification for breaking
a conduct]
naming a type of item, unnaming it (with name of <space>), naming it again
(new name or re-use of old one), then unnaming it again would issue
impossible: "named object not in disco"
throwing entire quiver and then picking the stack back up was not putting it
back into quiver
when reading a T-shirt or apron, add trailing period to the slogan unless
already present in the quoted text
when reading an engraving, suppress the addition of a trailing period if the
text already has one
cursed magic whistle could teleport hero on no-teleport levels
give a brief explanation when receiving a wish for acquiring the Amulet
teleportation traps no longer teleport you on levels made temporarily
no-teleport by the presence of a monster
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
@@ -2285,7 +2383,7 @@ curses: if user's terminal was set to 'application keypad mode' (DEC VTxxx
"ESC SPC G"), nethack wasn't recognizing number pad keys "ESC SPC G"), nethack wasn't recognizing number pad keys
curses: change petattr attributes, dropping support for curses-only ones curses: change petattr attributes, dropping support for curses-only ones
curses: swap the grey and no-color color initialization curses: swap the grey and no-color color initialization
curses+Qt: allow changing default colors with the 'palette' config option curses+tty+Qt: allow changing default colors with the 'palette' config option
(only if compiled with CHANGE_COLOR) (only if compiled with CHANGE_COLOR)
curses: if messages have been issued during start-up (for instance, warnings curses: if messages have been issued during start-up (for instance, warnings
about issues in run-time config file), prompt user to press <return> about issues in run-time config file), prompt user to press <return>
@@ -2475,6 +2573,8 @@ Unix: add ../include/nhlua.h to the alloc.o dependencies in Makefile.utl to
Unix: implement SELF_RECOVER compile-time option, on by default on linux Unix: implement SELF_RECOVER compile-time option, on by default on linux
Unix: allow build to succeed with musl (instead of glibc), by specifying Unix: allow build to succeed with musl (instead of glibc), by specifying
musl=1 on the make command line musl=1 on the make command line
Unix: support tilde expansion for home directory path, "~/relative-path", in
command line --nethackrc=path and environment NETHACKOPTIONS=@path
user_sounds: move the message hook from inside individual window display ports user_sounds: move the message hook from inside individual window display ports
to the core where it allows MSGTYP_NOSHOW msgtyp's to still trigger to the core where it allows MSGTYP_NOSHOW msgtyp's to still trigger
sounds to correct a reported github issue; also fixes a past reported sounds to correct a reported github issue; also fixes a past reported
@@ -2656,7 +2756,7 @@ menu for what-is command supports /^ and /" to view a list of nearby or whole
level visible and remembered traps level visible and remembered traps
spiders will occasionally spin webs when moving around spiders will occasionally spin webs when moving around
drinking a burning potion of oil will cure being turned into slime drinking a burning potion of oil will cure being turned into slime
new bigroom variants, a boulder maze and hexagons new bigroom variants, a boulder maze, hexagons, pillars
vomiting on an altar provokes the deities wrath vomiting on an altar provokes the deities wrath
branch stairs have a different glyph, show up in yellow color in tty branch stairs have a different glyph, show up in yellow color in tty
duration of confusion when drinking booze depends upon hunger state duration of confusion when drinking booze depends upon hunger state
@@ -2794,9 +2894,6 @@ wand of secret door detection, spell of detect unseen, and wizard mode ^E now
flash the cursor at each location where detection finds something flash the cursor at each location where detection finds something
saving-grace: once per game if receiving a killing blow from full or nearly saving-grace: once per game if receiving a killing blow from full or nearly
full HP, survive with 1 HP full HP, survive with 1 HP
livelog/#chronicle for saving-grace: if saving-grace prevents hero's death,
report it [at present, it uses the livelog classification for breaking
a conduct]
enlightenment/attribute disclosure for saving-grace: include a line for have enlightenment/attribute disclosure for saving-grace: include a line for have
or haven't been saved (game in progress) or did or didn't get saved or haven't been saved (game in progress) or did or didn't get saved
(game over) via saving-grace (game over) via saving-grace
@@ -2809,11 +2906,24 @@ enlightenment/attribute disclosure for saving-grace: include a line for have
tourists gain experience by "taking photos" of new creatures, and tourists gain experience by "taking photos" of new creatures, and
going to new dungeon levels going to new dungeon levels
healers gain experience by healing pets healers gain experience by healing pets
blessed scroll of destroy armor asks which armor to destroy blessed scroll of destroy armor asks which armor to destroy if wearing more
than one armor; otherwise it'll destroy a cursed armor, or erodes
random armor
archeologists' fedora is lucky archeologists' fedora is lucky
telepathic hero can discern which particular monster just read a scroll telepathic hero can discern which particular monster just read a scroll
add "make fetch-docs" to download pre-formatted documentation add "make fetch-docs" to download pre-formatted documentation
monsters will use throw-and-return weapons such as an aklys monsters will use throw-and-return weapons such as an aklys
archeologists can identify scrolls by deciphering their labels
monster destroy armor -spell first erodes armor
iron shoes protect the wearer against certain floor-based traps
ring of stealth prevents hero from leaving tracks
the game now automatically tracks which sell prices and buy prices you have
seen for each type of item; these are visible in the discoveries list,
and can also be shown elsewhere using the new 'price_quotes' option
new shields: shield of shock resistance, shield of drain resistance
new wand: wand of stasis
early-game monsters always miss with their first use of an attack wand
new command #toggle which can be used to toggle a boolean option
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
@@ -2872,7 +2982,7 @@ Unix: support --nethackrc=filename on the command line; same effect as
NETHACKOPTIONS='@filename' but leaves NETHACKOPTIONS available for NETHACKOPTIONS='@filename' but leaves NETHACKOPTIONS available for
specifying options; --no-nethackrc is same as --nethackrc=/dev/null specifying options; --no-nethackrc is same as --nethackrc=/dev/null
Windows: implement MSGHANDLER (pr #749 by argrath) Windows: implement MSGHANDLER (pr #749 by argrath)
Windows: Add configuration to support Curses on WinGUI (pr #1028 by chasonr) Windows: Add configuration to support Curses on WinGUI (pr #1028 by chasonr)
X11: implement 'selectsaved', restore via menu of saved games X11: implement 'selectsaved', restore via menu of saved games
X11: echo getline prompt and response (wishes, applying names) to message X11: echo getline prompt and response (wishes, applying names) to message
window and dumplog message history window and dumplog message history
@@ -3012,6 +3122,13 @@ split making pits on do_earthquake() into a separate function and
update the WASM cross-compile to work with the current update the WASM cross-compile to work with the current
code (pr #1331 by guillaumebrunerie) code (pr #1331 by guillaumebrunerie)
add silver maces (pr #1405 by disperse) add silver maces (pr #1405 by disperse)
applied several source comment spelling or grammar fixes that were linked
to an old rec.games.roguelike.nethack post from May 2006
by Arthur J. O'Dwyer
modernize code of LaTeX Guidebook (pr #1473 by Daniel Clow)
restore ability for a characteristic also resets exercise/abuse for that
characteristic (pr #1403 by greg-kennedy)
cross-compilation for the Amiga on Linux (pr #1494 by ingpaschke)
Code Cleanup and Reorganization Code Cleanup and Reorganization
@@ -3145,4 +3262,3 @@ relocate general-purpose function choose_classes_menu(), from
options.c to windows.c options.c to windows.c
remove register from variable declarations remove register from variable declarations
make glyph_to_cmap() a function instead of a macro make glyph_to_cmap() a function instead of a macro
+52 -4
View File
@@ -61,6 +61,7 @@ Set debugging flags.
| mongen | boolean | Do monsters generate | mongen | boolean | Do monsters generate
| hunger | boolean | Does hero's hunger-state increase | hunger | boolean | Does hero's hunger-state increase
| overwrite_stairs | boolean | Allow special-file commands overwrite the stairs | overwrite_stairs | boolean | Allow special-file commands overwrite the stairs
| prevent_pline | boolean | Prevent messages going out to the UI
|=== |===
Example: Example:
@@ -120,6 +121,15 @@ Example:
local k = nh.eckey("help"); local k = nh.eckey("help");
=== flip_level
Flip the level horizontally or vertically.
Example:
nh.flip_level(1);
=== getlin === getlin
Asks the player for a text to enter, and returns the entered string. Asks the player for a text to enter, and returns the entered string.
@@ -250,6 +260,26 @@ Example:
local str = nh.ing_suffix("foo"); local str = nh.ing_suffix("foo");
=== int_to_objname
Convert integer value to object name and class.
Returns two strings, the object base name and the class character.
The returned strings may be empty if an error occurred.
Example:
local oname, oclass = nh.int_to_objname(45);
=== int_to_pmname
Convert integer value to monster type name.
Example:
local pmname = nh.int_to_pmname(12);
=== is_genocided === is_genocided
Is specific monster type genocided? Returns a boolean value. Is specific monster type genocided? Returns a boolean value.
@@ -789,6 +819,7 @@ The hash parameter accepts the following keys:
| stunned | boolean | | stunned | boolean |
| confused | boolean | | confused | boolean |
| waiting | boolean | monster will wait until hero gets next to it | waiting | boolean | monster will wait until hero gets next to it
| m_lev_adj | integer | monster's level adjustment
| tail | boolean | generate worm without a tail? | tail | boolean | generate worm without a tail?
| group | boolean | generate a group of monsters? | group | boolean | generate a group of monsters?
| adjacentok | boolean | is adjacent location ok, if given one is not suitable? | adjacentok | boolean | is adjacent location ok, if given one is not suitable?
@@ -832,7 +863,7 @@ Example:
=== object === object
Create an object. Returns the object as an <<Obj>> class. Create an object and place it somewhere on the map. Returns the object as an <<Obj>> class.
The table parameter accepts the following: The table parameter accepts the following:
[options="header"] [options="header"]
@@ -856,8 +887,8 @@ The table parameter accepts the following:
| greased | boolean | Is the object greased? | greased | boolean | Is the object greased?
| broken | boolean | Is the object broken? | broken | boolean | Is the object broken?
| achievement | boolean | Is there an achievement attached to the object? | achievement | boolean | Is there an achievement attached to the object?
| x, y | int | Coordinates on the level | x, y | int | Coordinates on the level; defaults to a random location.
| coord | table | x,y coordinates in table format | coord | table | x,y coordinates in table format; defaults to a random location.
| montype | string | Monster id or class | montype | string | Monster id or class
| historic | boolean | Is statue historic? | historic | boolean | Is statue historic?
| male | boolean | Is statue male? | male | boolean | Is statue male?
@@ -1136,6 +1167,16 @@ Example:
local sel2 = selection.clone(sel); local sel2 = selection.clone(sel);
=== describe_size
Return a text describing the size of the selection.
Example:
local sel = selection.fillrect(1,1, 3,3);
local txt = sel:describe_size();
=== ellipse === ellipse
Example: Example:
@@ -1352,11 +1393,13 @@ Handling objects via obj-class.
=== new === new
Create a new object via wishing routine. Create a new object, either via wishing routine, or specifying object name and class.
Unlike des.object, does not place the object anywhere.
Example: Example:
local o = obj.new("rock"); local o = obj.new("rock");
local o = obj.new({ id = "invisibility", class = "!" });
=== isnull === isnull
@@ -1545,6 +1588,11 @@ These constants are in the `nhc` table.
|=== |===
| COLNO | Number of map columns | COLNO | Number of map columns
| ROWNO | Number of map rows | ROWNO | Number of map rows
| NUMMONS | Number of different monster types
| LOW_PM | First monster type id. See <<_int_to_pmname>>.
| HIGH_PM | Last monster type id. See <<_int_to_pmname>>.
| FIRST_OBJECT | First object type id. See <<_int_to_objname>>.
| LAST_OBJECT | Number of object type ids. See <<_int_to_objname>>.
| DLB | 1 or 0, depending if NetHack is compiled with DLB | DLB | 1 or 0, depending if NetHack is compiled with DLB
|=== |===
+1 -1
View File
@@ -99,7 +99,7 @@ only if it is present, to obtain
.B githash= .B githash=
and and
.B gitbranch= .B gitbranch=
info and include related preprocessor #defines in info and include related preprocessor #defines in
.I date.h .I date.h
file. file.
.br .br
+27 -27
View File
@@ -31,8 +31,8 @@ SHORT COMMANDS
the MDGREP FUNCTIONS section below for details. the MDGREP FUNCTIONS section below for details.
-m Generate date.h and options file. It will read dat/gitinfo.txt, -m Generate date.h and options file. It will read dat/gitinfo.txt,
only if it is present, to obtain githash= and gitbranch= only if it is present, to obtain githash= and gitbranch= info
info and include related preprocessor #defines in date.h file. and include related preprocessor #defines in date.h file.
-p Generate pm.h -p Generate pm.h
@@ -53,7 +53,7 @@ LONG COMMANDS
Show debugging output. Show debugging output.
--make [command] --make [command]
Execute a short command. Command is given without preceding Execute a short command. Command is given without preceding
dash. dash.
--input file --input file
@@ -61,66 +61,66 @@ LONG COMMANDS
is - standard input is read. is - standard input is read.
--output file --output file
Specify the output file for the command (if needed). If the Specify the output file for the command (if needed). If the
file is - standard output is written. file is - standard output is written.
--svs [delimiter] --svs [delimiter]
Generate a version string to standard output without a trailing Generate a version string to standard output without a trailing
newline. If specified, the delimiter is used between each part newline. If specified, the delimiter is used between each part
of the version string. of the version string.
--grep Filter the input file to the output file. See the MDGREP FUNC- --grep Filter the input file to the output file. See the MDGREP FUNC-
TIONS section below for information on controlling the filtering TIONS section below for information on controlling the filtering
operation. operation.
--grep-showvars --grep-showvars
Show the name and value for each variable known to the grep Show the name and value for each variable known to the grep
option. option.
--grep-trace --grep-trace
Turn on debug tracing for the grep function ( --grep must be Turn on debug tracing for the grep function ( --grep must be
specified as well). specified as well).
--grep-defined symbol --grep-defined symbol
Exit shell true (0) if symbol is known and defined, otherwise Exit shell true (0) if symbol is known and defined, otherwise
exit shell false (1). exit shell false (1).
--grep-define symbol --grep-define symbol
Force the value of symbol to be "defined." Symbol must already Force the value of symbol to be "defined." Symbol must already
be known to makedefs. be known to makedefs.
--grep-undef symbol --grep-undef symbol
Force the definition of symbol to be "undefined." Symbol must Force the definition of symbol to be "undefined." Symbol must
already be known to makedefs. already be known to makedefs.
MDGREP FUNCTIONS MDGREP FUNCTIONS
The --grep command (and certain other commands) filter their input, on The --grep command (and certain other commands) filter their input, on
a line-by-line basis, according to control lines embedded in the input a line-by-line basis, according to control lines embedded in the input
and on information gleaned from the NetHack(6) configuration. This and on information gleaned from the NetHack(6) configuration. This
allows certain changes such as embedding platform-specific documenta- allows certain changes such as embedding platform-specific documenta-
tion into the master documentation files. tion into the master documentation files.
Rules: Rules:
- The default conditional state is printing enabled. - The default conditional state is printing enabled.
- Any line NOT starting with a caret (^) is either suppressed - Any line NOT starting with a caret (^) is either suppressed
or passed through unchanged depending on the current condi- or passed through unchanged depending on the current condi-
tional state. tional state.
- Any line starting with a caret is a control line; as in C, - Any line starting with a caret is a control line; as in C,
zero or more spaces may be embedded in the line almost any- zero or more spaces may be embedded in the line almost any-
where (except immediately after the caret); however the where (except immediately after the caret); however the
caret must be in column 1. caret must be in column 1.
- Conditionals may be nested. - Conditionals may be nested.
- Makedefs will exit with an error code if any errors are - Makedefs will exit with an error code if any errors are
detected; processing will continue (if it can) to allow as detected; processing will continue (if it can) to allow as
many errors as possible to be detected. many errors as possible to be detected.
- Unknown identifiers are treated as both TRUE and as an - Unknown identifiers are treated as both TRUE and as an
error. Note that --undef or #undef in the NetHack(6) con- error. Note that --undef or #undef in the NetHack(6) con-
figuration are different from unknown. figuration are different from unknown.
Control lines: Control lines:
@@ -143,8 +143,8 @@ AUTHOR
The NetHack Development Team The NetHack Development Team
COPYRIGHT COPYRIGHT
This file is Copyright (C) Kenneth Lorber, 2024 for version This file is Copyright (C) Kenneth Lorber, 2024 for version
NetHack-3.7:1.22. NetHack may be freely redistributed. See license NetHack-3.7:1.22. NetHack may be freely redistributed. See license
for details. for details.
+1 -1
View File
@@ -136,7 +136,7 @@ b num \- i used to embolden italics
_bi \*Z mac \- \- print \*x in emboldened font 2, \*y after, _bi \*Z mac \- \- print \*x in emboldened font 2, \*y after,
\*z before \*z before
bm num 1i,1i+1v \- height of bottom margin bm num 1i,1i+1v \- height of bottom margin
_bt mac \- \- print pottom title _bt mac \- \- print bottom title
bt num .5i+1v \- bottom of footer to bottom of page bt num .5i+1v \- bottom of footer to bottom of page
_cf \*Z mac \- \- print contents of header line (double _cf \*Z mac \- \- print contents of header line (double
quotes around \*x, \*y before, \*z after) quotes around \*x, \*y before, \*z after)
+1 -1
View File
@@ -75,7 +75,7 @@ b num - i used to embolden italics
.bi x y z mac - - print x in emboldened font 2, y after, .bi x y z mac - - print x in emboldened font 2, y after,
z before z before
bm num 1i,1i+1v - height of bottom margin bm num 1i,1i+1v - height of bottom margin
.bt mac - - print pottom title .bt mac - - print bottom title
bt num .5i+1v - bottom of footer to bottom of page bt num .5i+1v - bottom of footer to bottom of page
.cf x y z mac - - print contents of header line (double .cf x y z mac - - print contents of header line (double
quotes around x, y before, z after) quotes around x, y before, z after)
+2
View File
@@ -36,6 +36,7 @@ REQUESTS
Macro What Initial Note Explanation Macro What Initial Note Explanation
Name It Is Value Name It Is Value
nH num 0 - avoid processing multiple times
.BR mac - - hard line break with vertical padding inserted .BR mac - - hard line break with vertical padding inserted
bR num - i bR num - i
.CC x y mac - - aligned one char key x with short definition y .CC x y mac - - aligned one char key x with short definition y
@@ -52,6 +53,7 @@ PX num - i
PY num - i PY num - i
.SD x mac - - .sd with options c-center i-indent n-no indent .SD x mac - - .sd with options c-center i-indent n-no indent
SF num - i SF num - i
UR mac - - URL passthrough for HTML generator
.UX mac - - .ux with updated trademark owner .UX mac - - .ux with updated trademark owner
+10 -5
View File
@@ -1,4 +1,4 @@
The definitition for each OPTIONS= option resides in include/optlist.h as of The definition for each OPTIONS= option resides in include/optlist.h as of
February 2020 in 3.7 WIP. February 2020 in 3.7 WIP.
Boolean and compound options are combined into a single allopt[] array. Boolean and compound options are combined into a single allopt[] array.
@@ -40,9 +40,14 @@ To add an entirely new option macro type:
iii) an initialization of an element in the allopt[] array, at iii) an initialization of an element in the allopt[] array, at
index opt_xxxx from step ii (xxxx is the option name). index opt_xxxx from step ii (xxxx is the option name).
2. Create the optfn_xxxx() function in options.c. Failure to do that will 2. If you are adding a boolean option, link it to a global variable
result in a link error of "undefined function optfn_xxxx." The functions are (e.g. in flags or iflags) and update optfn_boolean in options.c if
in options.c in alphabetical sequence by function name. necessary.
3. If you are not adding a boolean option, create the optfn_xxxx()
function in options.c. Failure to do that will result in a link error
of "undefined function optfn_xxxx." The functions are in options.c in
alphabetical sequence by function name.
The skeletal template for an optn_xxxx() function is: The skeletal template for an optn_xxxx() function is:
@@ -83,7 +88,7 @@ To add an entirely new option macro type:
return optn_ok; return optn_ok;
} }
3. NOTE: If you add (or delete) an option, please update the short 4. NOTE: If you add (or delete) an option, please update the short
options help (option_help()), the long options help (dat/opthelp) options help (option_help()), the long options help (dat/opthelp)
and also the Guidebooks. and also the Guidebooks.
+2 -2
View File
@@ -87,7 +87,7 @@ There are 4 distinct types of sound sound_triggers used by NetHack.
at the outset (ambience_begin), at the at the outset (ambience_begin), at the
termination (ambience_end), and termination (ambience_end), and
periodically in-between as needed periodically in-between as needed
(ambience_upate), likely with a different (ambience_update), likely with a different
hero proximity value. hero proximity value.
SOUND_TRIGGER_VERBAL Invoked by the core when someone (or something) SOUND_TRIGGER_VERBAL Invoked by the core when someone (or something)
@@ -233,7 +233,7 @@ sound_play_usersound(char *filename, int32_t volume, int32_t usidx);
sound_ambience(int32_t ambienceid, int32_t ambience_action, sound_ambience(int32_t ambienceid, int32_t ambience_action,
int32_t hero_proximity); int32_t hero_proximity);
-- NetHack will call this function when it wants a particular -- NetHack will call this function when it wants a particular
ambience related sound played in order to provide atomosphere ambience related sound played in order to provide atmosphere
or flavor. or flavor.
-- The ambienceid is used to identify the particular ambience sound -- The ambienceid is used to identify the particular ambience sound
being sought. The abienceid identifiers are from the being sought. The abienceid identifiers are from the
+1 -1
View File
@@ -29,7 +29,7 @@
.\" labeled paragraph label (and first line) .\" labeled paragraph label (and first line)
.de PL .de PL
.br .br
\\h'|-\\n(PYu'\\$1\\h'|-\\n(PXu'\ -\ \\c \" back up, output the label, then \\h'|-\\n(PYu'\\$1\\h'|-\\n(PXu'\ -\ \\c\" back up, output the label, then
. \" skip to width-of(" - ") before the . \" skip to width-of(" - ") before the
. \" normal indentation, output the " - " . \" normal indentation, output the " - "
. \" then attach the next line (the . \" then attach the next line (the
+5 -1
View File
@@ -284,7 +284,7 @@ update_inventory(arg)
-- For an argument of 0: -- For an argument of 0:
-- Indicate to the window port that the inventory has -- Indicate to the window port that the inventory has
been changed. been changed.
-- Merely calls display_inventory() for window-ports -- Merely calls repopulate_perminvent() for window-ports
that leave the window up, otherwise empty. that leave the window up, otherwise empty.
-- or for a non-zero argument: -- or for a non-zero argument:
-- Prompts the user for a menu scrolling action and -- Prompts the user for a menu scrolling action and
@@ -1001,6 +1001,10 @@ char display_inventory(lets, want_reply)
-- Calls a start_menu()/add_menu()/select_menu() sequence. -- Calls a start_menu()/add_menu()/select_menu() sequence.
It returns the item selected, or '\0' if none is selected. It returns the item selected, or '\0' if none is selected.
Returns '\033' if the menu was canceled. Returns '\033' if the menu was canceled.
void repopulate_perminvent(void)
-- a minimal alternative to display_inventory() that
focuses only on repopulating the permanent inventory
window.
raw_printf(str, ...) raw_printf(str, ...)
-- Like raw_print(), but accepts arguments like printf(). This -- Like raw_print(), but accepts arguments like printf(). This
routine processes the arguments and then calls raw_print(). routine processes the arguments and then calls raw_print().
@@ -17,6 +17,10 @@
#ifdef CROSS_TO_AMIGA #ifdef CROSS_TO_AMIGA
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <proto/dos.h>
#endif #endif
#ifdef __SASC_60 /* since SAS can prevent re-inclusion */ #ifdef __SASC_60 /* since SAS can prevent re-inclusion */
@@ -48,13 +52,9 @@ typedef long off_t;
#define PATHLEN 130 #define PATHLEN 130
/* data librarian defs */ /* data librarian defs */
#ifndef NOCWD_ASSUMPTIONS
#define DLBFILE "NetHack:nhdat" /* main library */
#define DLBFILE2 "NetHack:nhsdat" /* sound library */
#else
#define DLBFILE "nhdat" /* main library */ #define DLBFILE "nhdat" /* main library */
#define DLBFILE2 "nhsdat" /* sound library */ /* nhsdat sound library not used in 3.7 */
#endif #undef DLBFILE2
#ifndef CROSS_TO_AMIGA #ifndef CROSS_TO_AMIGA
#define FILENAME_CMP stricmp /* case insensitive */ #define FILENAME_CMP stricmp /* case insensitive */
@@ -193,21 +193,21 @@ void amii_setpens(int);
#define M(c) ((c) -128) #define M(c) ((c) -128)
#endif #endif
struct ami_sysflags { struct ami_sysflags {
char sysflagsid[10]; char sysflagsid[10];
#ifdef AMIFLUSH #ifdef AMIFLUSH
boolean altmeta; /* use ALT keys as META */ boolean altmeta; /* use ALT keys as META */
boolean amiflush; /* kill typeahead */ boolean amiflush; /* kill typeahead */
#endif #endif
#ifdef AMII_GRAPHICS #ifdef AMII_GRAPHICS
int numcols; int numcols;
unsigned short amii_dripens[20]; /* DrawInfo Pens currently there are 13 in v39 */ unsigned short amii_dripens[20]; /* DrawInfo Pens currently there are 13 in v39 */
AMII_COLOR_TYPE amii_curmap[AMII_MAXCOLORS]; /* colormap */ AMII_COLOR_TYPE amii_curmap[AMII_MAXCOLORS]; /* colormap */
#endif #endif
#ifdef OPT_DISPMAP #ifdef OPT_DISPMAP
boolean fast_map; /* use optimized, less flexible map display */ boolean fast_map; /* use optimized, less flexible map display */
#endif #endif
#ifdef MFLOPPY #ifdef MFLOPPY
boolean asksavedisk; boolean asksavedisk;
#endif #endif
}; };
extern struct ami_sysflags sysflags; extern struct ami_sysflags sysflags;
+1 -1
View File
@@ -197,7 +197,7 @@ static NEARDATA struct artifact artilist[] = {
* or the shriek that shrieked he, * or the shriek that shrieked he,
* As I gnashed my teeth, and from my sheath * As I gnashed my teeth, and from my sheath
* I drew my Snickersnee! * I drew my Snickersnee!
* --Koko, Lord high executioner of Titipu * --Ko-Ko, Lord high executioner of Titipu
* (From Sir W.S. Gilbert's "The Mikado") * (From Sir W.S. Gilbert's "The Mikado")
*/ */
A("Snickersnee", KATANA, SPFX_RESTR, 0, 0, PHYS(0, 8), NO_DFNS, NO_CARY, A("Snickersnee", KATANA, SPFX_RESTR, 0, 0, PHYS(0, 8), NO_DFNS, NO_CARY,
+3
View File
@@ -27,6 +27,9 @@ Astral Plane \GXXXXNNNN:123456 HP:1234(1234) Pw:1234(1234) AC:-127
#define MAXCO (COLNO + 40) #define MAXCO (COLNO + 40)
#endif #endif
/* limit of the player's name in the status window */
#define BOTL_NSIZ 16
struct condmap { struct condmap {
const char *id; const char *id;
unsigned long bitmask; unsigned long bitmask;
+5 -4
View File
@@ -149,10 +149,11 @@
#ifdef X11_GRAPHICS #ifdef X11_GRAPHICS
/* /*
* There are two ways that X11 tiles may be defined. (1) using a custom * There are two ways that X11 tiles may be defined:
* format loaded by NetHack code, or (2) using the XPM format loaded by * (1) using a custom format loaded by NetHack code.
* the free XPM library. The second option allows you to then use other * (2) using the XPM format loaded by the free XPM library.
* programs to generate tiles files. For example, the PBMPlus tools * The second option allows you to then use other programs to
* generate tiles files. For example, the PBMPlus tools
* would allow: * would allow:
* xpmtoppm <x11tiles.xpm | pnmscale 1.25 | ppmquant 90 | \ * xpmtoppm <x11tiles.xpm | pnmscale 1.25 | ppmquant 90 | \
* ppmtoxpm >x11tiles_big.xpm * ppmtoxpm >x11tiles_big.xpm
+1 -1
View File
@@ -95,7 +95,7 @@
#undef UNIX #undef UNIX
#define DLB #define DLB
#define HACKDIR "NetHack:" #define HACKDIR "NetHack:"
#define NO_MACRO_CPATH
#endif #endif
/* /*
+1 -1
View File
@@ -168,7 +168,7 @@ struct context_info {
boolean bypasses; /* bypass flag is set on at least one fobj */ boolean bypasses; /* bypass flag is set on at least one fobj */
boolean door_opened; /* set to true if door was opened during test_move */ boolean door_opened; /* set to true if door was opened during test_move */
boolean resume_wish; /* game was exited while in wish prompt */ boolean resume_wish; /* game was exited while in wish prompt */
boolean tips[NUM_TIPS]; unsigned long tips;
struct dig_info digging; struct dig_info digging;
struct victual_info victual; struct victual_info victual;
struct engrave_info engraving; struct engrave_info engraving;
+1
View File
@@ -59,6 +59,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#include <time.h> #include <time.h>
#include <limits.h>
#else /* !__cplusplus */ #else /* !__cplusplus */
/* for FILE */ /* for FILE */
+10 -1
View File
@@ -240,6 +240,7 @@ struct instance_globals_c {
/* decl.c */ /* decl.c */
char chosen_windowtype[WINTYPELEN]; char chosen_windowtype[WINTYPELEN];
int cmd_key; /* parse() / rhack() */ int cmd_key; /* parse() / rhack() */
struct Cmd_bind *cmd_bind;
cmdcount_nht command_count; cmdcount_nht command_count;
/* some objects need special handling during destruction or placement */ /* some objects need special handling during destruction or placement */
struct obj *current_wand; /* wand currently zapped/applied */ struct obj *current_wand; /* wand currently zapped/applied */
@@ -475,6 +476,7 @@ struct instance_globals_i {
/* invent.c */ /* invent.c */
char *invbuf; char *invbuf;
unsigned invbufsiz; unsigned invbufsiz;
boolean item_action_in_progress;
int in_sync_perminvent; int in_sync_perminvent;
/* mon.c */ /* mon.c */
@@ -723,7 +725,8 @@ struct instance_globals_o {
/* options.c */ /* options.c */
int opt_phase; /* builtin_opt, syscf_, rc_file_, environ_, play_opt */ /* builtin_opt, syscf_, rc_file_, environ_, play_opt */
enum option_phases opt_phase;
boolean opt_initial; boolean opt_initial;
boolean opt_from_file; boolean opt_from_file;
boolean opt_need_redraw; /* for doset() */ boolean opt_need_redraw; /* for doset() */
@@ -837,6 +840,9 @@ struct instance_globals_r {
struct instance_globals_s { struct instance_globals_s {
/* allmain.c */
boolean saving_grace_turn; /* saving grace was triggered this turn */
/* artifact.c */ /* artifact.c */
int spec_dbon_applies; /* coordinate effects from spec_dbon() with int spec_dbon_applies; /* coordinate effects from spec_dbon() with
messages in artifact_hit() */ messages in artifact_hit() */
@@ -968,6 +974,9 @@ struct instance_globals_t {
struct instance_globals_u { struct instance_globals_u {
/* allmain.c */
int uhp_at_start_of_monster_turn;
/* botl.c */ /* botl.c */
boolean update_all; boolean update_all;
+1 -1
View File
@@ -43,7 +43,7 @@ struct tmpbranch {
}; };
/* /*
* Values for type for tmpbranch structure. * Values for type in tmpbranch structure.
*/ */
#define TBR_STAIR 0 /* connection with both ends having a staircase */ #define TBR_STAIR 0 /* connection with both ends having a staircase */
#define TBR_NO_UP 1 /* connection with no up staircase */ #define TBR_NO_UP 1 /* connection with no up staircase */
+1 -1
View File
@@ -169,7 +169,7 @@ struct linfo {
/* 0x02 was FORGOTTEN, when amnesia made you forget maps */ /* 0x02 was FORGOTTEN, when amnesia made you forget maps */
#define LFILE_EXISTS 0x04 /* a level file exists for this level */ #define LFILE_EXISTS 0x04 /* a level file exists for this level */
/* Note: VISITED and LFILE_EXISTS are currently almost always /* Note: VISITED and LFILE_EXISTS are currently almost always
* set at the same time. However they _mean_ different things. * set at the same time. However, they _mean_ different things.
*/ */
}; };
+2
View File
@@ -13,6 +13,8 @@ enum engraving_texts {
text_states text_states
}; };
#define engr_text_space(ep) ((char *) ((ep) + 1))
struct engr { struct engr {
struct engr *nxt_engr; struct engr *nxt_engr;
char *engr_txt[text_states]; char *engr_txt[text_states];
+84 -21
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 extern.h $NHDT-Date: 1738638877 2025/02/03 19:14:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1476 $ */ /* NetHack 3.7 extern.h $NHDT-Date: 1770949988 2026/02/12 18:33:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1523 $ */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -71,6 +71,10 @@
#include "artifact.h" #include "artifact.h"
#endif #endif
#ifndef MFNDPOS_H
#include "mfndpos.h"
#endif
/* ### alloc.c ### */ /* ### alloc.c ### */
#if 0 #if 0
@@ -101,7 +105,6 @@ extern void stop_occupation(void);
extern void init_sound_disp_gamewindows(void); extern void init_sound_disp_gamewindows(void);
extern void newgame(void); extern void newgame(void);
extern void welcome(boolean); extern void welcome(boolean);
extern int argcheck(int, char **, enum earlyarg);
extern long timet_to_seconds(time_t); extern long timet_to_seconds(time_t);
extern long timet_delta(time_t, time_t); extern long timet_delta(time_t, time_t);
@@ -258,6 +261,7 @@ extern void free_ebones(struct monst *) NONNULLARG1;
/* ### botl.c ### */ /* ### botl.c ### */
extern char *get_strength_str(void);
extern char *do_statusline1(void); extern char *do_statusline1(void);
extern void check_gold_symbol(void); extern void check_gold_symbol(void);
extern char *do_statusline2(void); extern char *do_statusline2(void);
@@ -331,6 +335,15 @@ extern boolean parse_conf_file(FILE *fp, boolean (*proc)(char *arg));
extern void set_configfile_name(const char *); extern void set_configfile_name(const char *);
extern char *get_configfile(void); extern char *get_configfile(void);
extern const char *get_default_configfile(void); extern const char *get_default_configfile(void);
extern void rcfile(void);
extern void rcfile_interface_options(void);
extern void heed_all_config_statements(void);
extern void disregard_all_config_statements(void);
extern void heed_this_config_statement(int);
extern void disregard_this_config_statement(int);
extern boolean config_unmatched_ignored(void);
extern void clear_ignore_errors_on_unmatched(void);
extern void set_ignore_errors_on_unmatched(void);
/* ### coloratt.c ### */ /* ### coloratt.c ### */
@@ -365,6 +378,8 @@ extern void change_palette(void);
/* ### cmd.c ### */ /* ### cmd.c ### */
extern void cmdbind_freeall(void);
extern int dotoggleoption(void);
extern void set_move_cmd(int, int); extern void set_move_cmd(int, int);
extern int do_move_west(void); extern int do_move_west(void);
extern int do_move_northwest(void); extern int do_move_northwest(void);
@@ -442,10 +457,10 @@ extern int doextlist(void);
extern int extcmd_via_menu(void); extern int extcmd_via_menu(void);
extern int enter_explore_mode(void); extern int enter_explore_mode(void);
extern boolean bind_mousebtn(int, const char *); extern boolean bind_mousebtn(int, const char *);
extern boolean bind_key(uchar, const char *); extern boolean bind_key(uchar, const char *, boolean);
extern void dokeylist(void); extern void dokeylist(void);
extern int xytod(coordxy, coordxy); extern int xytodir(int, int);
extern void dtoxy(coord *, int); extern void dirtocoord(coord *, int);
extern int movecmd(char, int); extern int movecmd(char, int);
extern int dxdy_moveok(void); extern int dxdy_moveok(void);
extern int getdir(const char *); extern int getdir(const char *);
@@ -746,6 +761,7 @@ extern void Ring_gone(struct obj *) NONNULLARG1;
extern void Blindf_on(struct obj *) NONNULLARG1; extern void Blindf_on(struct obj *) NONNULLARG1;
extern void Blindf_off(struct obj *); extern void Blindf_off(struct obj *);
extern int dotakeoff(void); extern int dotakeoff(void);
extern int ia_dotakeoff(void);
extern int doremring(void); extern int doremring(void);
extern int cursed(struct obj *); extern int cursed(struct obj *);
extern int armoroff(struct obj *); extern int armoroff(struct obj *);
@@ -760,7 +776,8 @@ extern struct obj *unchanger(void);
extern void reset_remarm(void); extern void reset_remarm(void);
extern int doddoremarm(void); extern int doddoremarm(void);
extern int remarm_swapwep(void); extern int remarm_swapwep(void);
extern int destroy_arm(struct obj *); extern int disintegrate_arm(struct obj *);
extern int destroy_arm(void);
extern void adj_abon(struct obj *, schar) NONNULLARG1; extern void adj_abon(struct obj *, schar) NONNULLARG1;
extern boolean inaccessible_equipment(struct obj *, const char *, boolean); extern boolean inaccessible_equipment(struct obj *, const char *, boolean);
extern int any_worn_armor_ok(struct obj *); extern int any_worn_armor_ok(struct obj *);
@@ -823,6 +840,7 @@ extern void hurtle(int, int, int, boolean);
extern void mhurtle(struct monst *, int, int, int) NONNULLARG1; extern void mhurtle(struct monst *, int, int, int) NONNULLARG1;
extern boolean harmless_missile(struct obj *) NONNULLARG1; extern boolean harmless_missile(struct obj *) NONNULLARG1;
extern boolean throwing_weapon(struct obj *) NONNULLARG1; extern boolean throwing_weapon(struct obj *) NONNULLARG1;
extern boolean throwit_mon_hit(struct obj *, struct monst *) NONNULLARG1;
extern void throwit(struct obj *, long, boolean, struct obj *) NONNULLARG1; extern void throwit(struct obj *, long, boolean, struct obj *) NONNULLARG1;
extern int omon_adj(struct monst *, struct obj *, boolean) NONNULLPTRS; extern int omon_adj(struct monst *, struct obj *, boolean) NONNULLPTRS;
extern boolean should_mulch_missile(struct obj *); extern boolean should_mulch_missile(struct obj *);
@@ -910,6 +928,14 @@ extern void overview_stats(winid, const char *, long *, long *) NONNULLPTRS;
extern void remdun_mapseen(int); extern void remdun_mapseen(int);
extern const char *endgamelevelname(char *, int); extern const char *endgamelevelname(char *, int);
/* ### earlyarg.c ### */
extern int argcheck(int, char **, enum earlyarg);
extern void early_options(int *argc_p, char ***argv_p, char **hackdir_p);
#ifdef WIN32
int windows_early_options(const char *);
#endif
/* ### eat.c ### */ /* ### eat.c ### */
extern void eatmupdate(void); extern void eatmupdate(void);
@@ -1155,6 +1181,7 @@ extern void dump_glyphids(void);
extern void clear_all_glyphmap_colors(void); extern void clear_all_glyphmap_colors(void);
extern void reset_customcolors(void); extern void reset_customcolors(void);
extern int glyph_to_cmap(int); extern int glyph_to_cmap(int);
extern void maybe_shuffle_customizations(void);
/* ### hack.c ### */ /* ### hack.c ### */
@@ -1233,6 +1260,10 @@ extern boolean pmatchi(const char *, const char *) NONNULLPTRS;
extern boolean pmatchz(const char *, const char *) NONNULLPTRS; extern boolean pmatchz(const char *, const char *) NONNULLPTRS;
*/ */
/* ### iactions.c ### */
extern int itemactions(struct obj *otmp) NONNULLARG1;
/* ### insight.c ### */ /* ### insight.c ### */
extern int doattributes(void); extern int doattributes(void);
@@ -1356,6 +1387,7 @@ extern void sync_perminvent(void);
extern void perm_invent_toggled(boolean negated); extern void perm_invent_toggled(boolean negated);
extern void prepare_perminvent(winid window); extern void prepare_perminvent(winid window);
extern struct obj *carrying_stoning_corpse(void); extern struct obj *carrying_stoning_corpse(void);
extern void repopulate_perminvent(void);
/* ### ioctl.c ### */ /* ### ioctl.c ### */
@@ -1531,7 +1563,7 @@ extern int monster_census(boolean);
extern int msummon(struct monst *); extern int msummon(struct monst *);
extern void summon_minion(aligntyp, boolean); extern void summon_minion(aligntyp, boolean);
extern int demon_talk(struct monst *) NONNULLARG1; extern int demon_talk(struct monst *) NONNULLARG1;
extern long bribe(struct monst *) NONNULLARG1; extern long bribe(struct monst *, const char *) NONNULLARG12;
extern int dprince(aligntyp); extern int dprince(aligntyp);
extern int dlord(aligntyp); extern int dlord(aligntyp);
extern int llord(void); extern int llord(void);
@@ -1654,6 +1686,7 @@ extern struct obj *mk_named_object(int, struct permonst *,
coordxy, coordxy, coordxy, coordxy,
const char *) ; const char *) ;
extern struct obj *rnd_treefruit_at(coordxy, coordxy); extern struct obj *rnd_treefruit_at(coordxy, coordxy);
extern boolean is_treefruit(struct obj *) NONNULLARG1;
extern void set_corpsenm(struct obj *, int) NONNULLARG1; extern void set_corpsenm(struct obj *, int) NONNULLARG1;
extern long rider_revival_time(struct obj *, boolean) NONNULLARG1; extern long rider_revival_time(struct obj *, boolean) NONNULLARG1;
extern void start_corpse_timeout(struct obj *) NONNULLARG1; extern void start_corpse_timeout(struct obj *) NONNULLARG1;
@@ -1743,7 +1776,7 @@ extern boolean can_touch_safely(struct monst *, struct obj *) NONNULLARG12;
extern int can_carry(struct monst *, struct obj *) NONNULLARG12; extern int can_carry(struct monst *, struct obj *) NONNULLARG12;
extern long mon_allowflags(struct monst *) NONNULLARG1; extern long mon_allowflags(struct monst *) NONNULLARG1;
extern boolean m_in_air(struct monst *) NONNULLARG1; extern boolean m_in_air(struct monst *) NONNULLARG1;
extern int mfndpos(struct monst *, coord *, long *, long) NONNULLPTRS; extern int mfndpos(struct monst *, struct mfndposdata *, long) NONNULLPTRS;
extern boolean monnear(struct monst *, coordxy, coordxy) NONNULLARG1; extern boolean monnear(struct monst *, coordxy, coordxy) NONNULLARG1;
extern void dmonsfree(void); extern void dmonsfree(void);
extern void elemental_clog(struct monst *) NONNULLARG1; extern void elemental_clog(struct monst *) NONNULLARG1;
@@ -1913,8 +1946,8 @@ extern boolean accessible(coordxy, coordxy);
extern void set_apparxy(struct monst *) NONNULLARG1; extern void set_apparxy(struct monst *) NONNULLARG1;
extern boolean can_ooze(struct monst *) NONNULLARG1; extern boolean can_ooze(struct monst *) NONNULLARG1;
extern boolean can_fog(struct monst *) NONNULLARG1; extern boolean can_fog(struct monst *) NONNULLARG1;
extern boolean should_displace(struct monst *, coord *, long *, int, coordxy, extern boolean should_displace(struct monst *, const struct mfndposdata *,
coordxy) NONNULLPTRS; coordxy, coordxy) NONNULLPTRS;
extern boolean undesirable_disp(struct monst *, coordxy, coordxy) NONNULLARG1; extern boolean undesirable_disp(struct monst *, coordxy, coordxy) NONNULLARG1;
extern boolean can_hide_under_obj(struct obj *); extern boolean can_hide_under_obj(struct obj *);
@@ -1952,7 +1985,7 @@ extern long filesize(char *);
#endif /* MSDOS */ #endif /* MSDOS */
extern char *foundfile_buffer(void); extern char *foundfile_buffer(void);
#endif /* __GO32__ */ #endif /* __GO32__ */
extern void chdrive(char *); extern void chdrive(const char *);
#ifndef TOS #ifndef TOS
extern void disable_ctrlP(void); extern void disable_ctrlP(void);
extern void enable_ctrlP(void); extern void enable_ctrlP(void);
@@ -2151,7 +2184,8 @@ extern boolean objdescr_is(struct obj *, const char *) NONNULLARG2;
extern void oinit(void); extern void oinit(void);
extern void savenames(NHFILE *) NONNULLARG1; extern void savenames(NHFILE *) NONNULLARG1;
extern void restnames(NHFILE *) NONNULLARG1; extern void restnames(NHFILE *) NONNULLARG1;
extern void discover_object(int, boolean, boolean); extern void observe_object(struct obj *) NONNULLARG1;
extern void discover_object(int, boolean, boolean, boolean);
extern void undiscover_object(int); extern void undiscover_object(int);
extern boolean interesting_to_discover(int); extern boolean interesting_to_discover(int);
extern int choose_disco_sort(int); extern int choose_disco_sort(int);
@@ -2268,6 +2302,7 @@ extern char *get_option_value(const char *, boolean) NONNULLARG1;
extern int doset_simple(void); extern int doset_simple(void);
extern int doset(void); extern int doset(void);
extern int dotogglepickup(void); extern int dotogglepickup(void);
extern int toggle_bool_option(const char *);
extern void option_help(void); extern void option_help(void);
extern void all_options_strbuf(strbuf_t *) NONNULLARG1; extern void all_options_strbuf(strbuf_t *) NONNULLARG1;
extern void next_opt(winid, const char *) NONNULLARG2; extern void next_opt(winid, const char *) NONNULLARG2;
@@ -2294,6 +2329,11 @@ extern int msgtype_type(const char *, boolean) NONNULLARG1;
extern void hide_unhide_msgtypes(boolean, int); extern void hide_unhide_msgtypes(boolean, int);
extern void msgtype_free(void); extern void msgtype_free(void);
extern void options_free_window_colors(void); extern void options_free_window_colors(void);
extern void heed_all_options(void);
extern void disregard_all_options(void);
extern void heed_this_option(enum opt);
extern void disregard_this_option(enum opt);
extern void clear_ignore_errors_on_unmatched(void);
#ifdef TTY_PERM_INVENT #ifdef TTY_PERM_INVENT
extern void check_perm_invent_again(void); extern void check_perm_invent_again(void);
#endif #endif
@@ -2319,12 +2359,13 @@ extern int dowhatdoes(void);
extern char *dowhatdoes_core(char, char *) NONNULLARG2; /*might return NULL*/ extern char *dowhatdoes_core(char, char *) NONNULLARG2; /*might return NULL*/
extern int dohelp(void); extern int dohelp(void);
extern int dohistory(void); extern int dohistory(void);
void allopt_array_init(void);
/* ### xxmain.c ### */ /* ### xxmain.c ### */
#if defined(MICRO) || defined(WIN32) #if defined(UNIX) || defined(MICRO) || defined(WIN32)
#ifdef CHDIR #ifdef CHDIR
extern void chdirx(char *, boolean); extern void chdirx(const char *, boolean);
#endif /* CHDIR */ #endif /* CHDIR */
extern boolean authorize_wizard_mode(void); extern boolean authorize_wizard_mode(void);
extern boolean authorize_explore_mode(void); extern boolean authorize_explore_mode(void);
@@ -2401,8 +2442,9 @@ extern int query_category(const char *, struct obj *, int, menu_item **, int) NO
/* dotypeinv() call query_objlist with NULL arg1 */ /* dotypeinv() call query_objlist with NULL arg1 */
extern int query_objlist(const char *, struct obj **, int, menu_item **, int, extern int query_objlist(const char *, struct obj **, int, menu_item **, int,
boolean(*)(struct obj *)) NONNULLARG24; boolean(*)(struct obj *)) NONNULLARG24;
extern boolean reroll_menu(void);
extern struct obj *pick_obj(struct obj *) NONNULLARG1; extern struct obj *pick_obj(struct obj *) NONNULLARG1;
extern int encumber_msg(void); extern void encumber_msg(void);
extern int container_at(coordxy, coordxy, boolean); extern int container_at(coordxy, coordxy, boolean);
extern int doloot(void); extern int doloot(void);
extern void observe_quantum_cat(struct obj *, boolean, boolean) NONNULLARG1; extern void observe_quantum_cat(struct obj *, boolean, boolean) NONNULLARG1;
@@ -2694,6 +2736,9 @@ void restore_gamelog(NHFILE *);
boolean restgamestate(NHFILE *); boolean restgamestate(NHFILE *);
void restore_msghistory(NHFILE *); void restore_msghistory(NHFILE *);
#endif #endif
extern void rest_adjust_levelflags(void);
extern void moves_to_relative_time(long *);
extern void relative_time_to_moves(long *);
/* ### rip.c ### */ /* ### rip.c ### */
@@ -2846,6 +2891,8 @@ extern void bclose(int);
/* setpaid() has a conditional code block near the end of the /* setpaid() has a conditional code block near the end of the
function, where arg1 is tested for NULL, preventing NONNULLARG1 */ function, where arg1 is tested for NULL, preventing NONNULLARG1 */
extern void setpaid(struct monst *) NO_NNARGS; extern void setpaid(struct monst *) NO_NNARGS;
extern void record_price_quote(int, unsigned long, boolean);
extern void append_price_quote(char *, char **, int) NONNULLARG12;
extern long money2mon(struct monst *, long) NONNULLARG1; extern long money2mon(struct monst *, long) NONNULLARG1;
extern void money2u(struct monst *, long) NONNULLARG1; extern void money2u(struct monst *, long) NONNULLARG1;
extern void shkgone(struct monst *) NONNULLARG1; extern void shkgone(struct monst *) NONNULLARG1;
@@ -2923,6 +2970,8 @@ extern void globby_bill_fixup(struct obj *, struct obj *) NONNULLARG12;
extern void credit_report(struct monst *shkp, int idx, extern void credit_report(struct monst *shkp, int idx,
boolean silent) NONNULLARG1; boolean silent) NONNULLARG1;
extern void use_unpaid_trapobj(struct obj *, coordxy, coordxy) NONNULLARG1; extern void use_unpaid_trapobj(struct obj *, coordxy, coordxy) NONNULLARG1;
extern void noisy_shop(struct mkroom *);
/* ### shknam.c ### */ /* ### shknam.c ### */
@@ -3019,6 +3068,8 @@ extern int nhl_abs_coord(lua_State *) NONNULLARG1;
extern void update_croom(void); extern void update_croom(void);
extern const char *get_trapname_bytype(int); extern const char *get_trapname_bytype(int);
extern void l_register_des(lua_State *) NONNULLARG1; extern void l_register_des(lua_State *) NONNULLARG1;
extern int get_table_objclass(lua_State *) NONNULLARG1;
extern int get_table_objtype(lua_State *) NONNULLARG1;
#endif /* !CROSSCOMPILE || CROSSCOMPILE_TARGET */ #endif /* !CROSSCOMPILE || CROSSCOMPILE_TARGET */
/* ### spell.c ### */ /* ### spell.c ### */
@@ -3035,6 +3086,7 @@ extern int spelleffects(int, boolean, boolean);
extern int tport_spell(int); extern int tport_spell(int);
extern void losespells(void); extern void losespells(void);
extern int dovspell(void); extern int dovspell(void);
extern void show_spells(void);
extern void initialspell(struct obj *) NONNULLARG1; extern void initialspell(struct obj *) NONNULLARG1;
extern int known_spell(short); extern int known_spell(short);
extern int spell_idx(short); extern int spell_idx(short);
@@ -3305,7 +3357,9 @@ extern void check_twitch(void);
/* ### u_init.c ### */ /* ### u_init.c ### */
extern void u_init(void); extern void u_init_misc(void);
extern void u_init_inventory_attrs(void);
extern void u_init_skills_discoveries(void);
/* ### uhitm.c ### */ /* ### uhitm.c ### */
@@ -3417,6 +3471,8 @@ extern int passive(struct monst *, struct obj *, boolean, boolean, uchar,
extern void passive_obj(struct monst *, struct obj *, struct attack *) NONNULLARG1; extern void passive_obj(struct monst *, struct obj *, struct attack *) NONNULLARG1;
extern void that_is_a_mimic(struct monst *, unsigned) NONNULLARG1; extern void that_is_a_mimic(struct monst *, unsigned) NONNULLARG1;
extern void stumble_onto_mimic(struct monst *) NONNULLARG1; extern void stumble_onto_mimic(struct monst *) NONNULLARG1;
extern boolean disguised_as_non_mon(struct monst *) NONNULLARG1;
extern boolean disguised_as_mon(struct monst *) NONNULLARG1;
extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12; extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12;
extern void light_hits_gremlin(struct monst *, int) NONNULLARG1; extern void light_hits_gremlin(struct monst *, int) NONNULLARG1;
@@ -3433,8 +3489,8 @@ extern void append_slash(char *) NONNULLARG1;
extern boolean check_user_string(const char *) NONNULLARG1; extern boolean check_user_string(const char *) NONNULLARG1;
extern char *get_login_name(void); extern char *get_login_name(void);
extern unsigned long sys_random_seed(void); extern unsigned long sys_random_seed(void);
ATTRNORETURN extern void after_opt_showpaths(const char *) NORETURN;
#endif /* UNIX */ #endif /* UNIX */
ATTRNORETURN extern void after_opt_showpaths(const char *) NORETURN;
/* ### unixtty.c ### */ /* ### unixtty.c ### */
@@ -3668,6 +3724,7 @@ extern void dry_a_towel(struct obj *, int, boolean) NONNULLARG1;
extern char *skill_level_name(int, char *) NONNULLARG2; extern char *skill_level_name(int, char *) NONNULLARG2;
extern const char *skill_name(int); extern const char *skill_name(int);
extern boolean can_advance(int, boolean); extern boolean can_advance(int, boolean);
extern void show_skills(void);
extern int enhance_weapon_skill(void); extern int enhance_weapon_skill(void);
extern void unrestrict_weapon_skill(int); extern void unrestrict_weapon_skill(int);
extern void use_skill(int, int); extern void use_skill(int, int);
@@ -3832,6 +3889,7 @@ extern void wizcustom_callback(winid win, int glyphnum, char *id);
#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG) #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG)
extern int wiz_display_macros(void); extern int wiz_display_macros(void);
extern int wiz_mon_diff(void); extern int wiz_mon_diff(void);
extern int wiz_objprobs(void);
#endif #endif
extern void sanity_check(void); extern void sanity_check(void);
@@ -3869,9 +3927,11 @@ extern void setworn(struct obj *, long) NO_NNARGS; /* has tests for obj */
extern void setnotworn(struct obj *) NO_NNARGS; /* has tests for obj */ extern void setnotworn(struct obj *) NO_NNARGS; /* has tests for obj */
extern void allunworn(void); extern void allunworn(void);
extern struct obj *wearmask_to_obj(long); extern struct obj *wearmask_to_obj(long);
extern int wornmask_to_armcat(long);
extern long armcat_to_wornmask(int);
extern long wearslot(struct obj *) NONNULLARG1; extern long wearslot(struct obj *) NONNULLARG1;
extern void check_wornmask_slots(void); extern void check_wornmask_slots(void);
extern void mon_set_minvis(struct monst *) NONNULLARG1; extern void mon_set_minvis(struct monst *, boolean) NONNULLARG1;
extern void mon_adjust_speed(struct monst *, int, struct obj *) NONNULLARG1; extern void mon_adjust_speed(struct monst *, int, struct obj *) NONNULLARG1;
extern void update_mon_extrinsics(struct monst *, struct obj *, boolean, extern void update_mon_extrinsics(struct monst *, struct obj *, boolean,
boolean) NONNULLARG12; boolean) NONNULLARG12;
@@ -3937,16 +3997,17 @@ extern int spell_damage_bonus(int);
extern const char *exclam(int force) NONNULL; extern const char *exclam(int force) NONNULL;
extern void hit(const char *, struct monst *, const char *) NONNULLPTRS; extern void hit(const char *, struct monst *, const char *) NONNULLPTRS;
extern void miss(const char *, struct monst *) NONNULLPTRS; extern void miss(const char *, struct monst *) NONNULLPTRS;
extern struct monst *bhit(coordxy, coordxy, int, enum bhit_call_types, extern struct monst *bhit(int, int, int, enum bhit_call_types,
int(*)(struct monst *, struct obj *), int(*)(struct monst *, struct obj *),
int(*)(struct obj *, struct obj *), int(*)(struct obj *, struct obj *),
struct obj **) NONNULLARG7; struct obj **) NONNULLARG7;
extern struct monst *boomhit(struct obj *, coordxy, coordxy) NONNULLARG1; extern struct monst *boomhit(struct obj *, int, int) NONNULLARG1;
extern int zhitm(struct monst *, int, int, struct obj **) NONNULLPTRS; extern int zhitm(struct monst *, int, int, struct obj **) NONNULLPTRS;
extern int burn_floor_objects(coordxy, coordxy, boolean, boolean); extern int burn_floor_objects(coordxy, coordxy, boolean, boolean);
extern void ubuzz(int, int); extern void ubuzz(int, int);
extern void buzz(int, int, coordxy, coordxy, int, int); extern void buzz(int, int, coordxy, coordxy, int, int);
extern void dobuzz(int, int, coordxy, coordxy, int, int, boolean); extern void dobuzz(int, int, coordxy, coordxy, int, int,
boolean, boolean, boolean);
extern void melt_ice(coordxy, coordxy, const char *) NO_NNARGS; extern void melt_ice(coordxy, coordxy, const char *) NO_NNARGS;
extern void start_melt_ice_timeout(coordxy, coordxy, long); extern void start_melt_ice_timeout(coordxy, coordxy, long);
extern void melt_ice_away(union any *, long) NONNULLARG1; extern void melt_ice_away(union any *, long) NONNULLARG1;
@@ -3960,6 +4021,8 @@ extern boolean inventory_resistance_check(int);
extern char *item_what(int); extern char *item_what(int);
extern int destroy_items(struct monst *, int, int) NONNULLARG1; extern int destroy_items(struct monst *, int, int) NONNULLARG1;
extern int resist(struct monst *, char, int, int) NONNULLARG1; extern int resist(struct monst *, char, int, int) NONNULLARG1;
extern void wish_history_add(char *);
extern void wish_history_flush(void);
extern void makewish(void); extern void makewish(void);
extern const char *flash_str(int, boolean) NONNULL; extern const char *flash_str(int, boolean) NONNULL;
+4 -1
View File
@@ -254,6 +254,7 @@ struct instance_flags {
boolean remember_getpos; /* save getpos() positioning in do-again queue */ boolean remember_getpos; /* save getpos() positioning in do-again queue */
boolean sad_feeling; /* unseen pet is dying */ boolean sad_feeling; /* unseen pet is dying */
boolean showdamage; /* extra message reporting damage hero has taken */ boolean showdamage; /* extra message reporting damage hero has taken */
boolean pending_customizations; /* at least one custom. was specified */
xint8 debug_fuzzer; /* fuzz testing */ xint8 debug_fuzzer; /* fuzz testing */
int at_midnight; /* only valid during end of game disclosure */ int at_midnight; /* only valid during end of game disclosure */
int at_night; /* also only valid during end of game disclosure */ int at_night; /* also only valid during end of game disclosure */
@@ -292,6 +293,7 @@ struct instance_flags {
boolean debug_overwrite_stairs; /* debug: allow overwriting stairs */ boolean debug_overwrite_stairs; /* debug: allow overwriting stairs */
boolean debug_mongen; /* debug: prevent monster generation */ boolean debug_mongen; /* debug: prevent monster generation */
boolean debug_hunger; /* debug: prevent hunger */ boolean debug_hunger; /* debug: prevent hunger */
boolean debug_prevent_pline; /* debug: prevent pline going to UI */
boolean mon_polycontrol; /* debug: control monster polymorphs */ boolean mon_polycontrol; /* debug: control monster polymorphs */
boolean mon_telecontrol; /* debug: control monster teleports */ boolean mon_telecontrol; /* debug: control monster teleports */
boolean in_dumplog; /* doing the dumplog right now? */ boolean in_dumplog; /* doing the dumplog right now? */
@@ -328,6 +330,7 @@ struct instance_flags {
boolean num_pad; /* use numbers for movement commands */ boolean num_pad; /* use numbers for movement commands */
boolean perm_invent; /* display persistent inventory window */ boolean perm_invent; /* display persistent inventory window */
boolean perm_invent_pending; /* need to try again */ boolean perm_invent_pending; /* need to try again */
boolean pricequotes; /* display price quotes on unIDd objects */
boolean renameallowed; /* can change hero name during role selection */ boolean renameallowed; /* can change hero name during role selection */
boolean renameinprogress; /* we are changing hero name */ boolean renameinprogress; /* we are changing hero name */
boolean sounds; /* master on/off switch for using soundlib */ boolean sounds; /* master on/off switch for using soundlib */
@@ -481,7 +484,7 @@ struct instance_flags {
}; };
/* /*
* Old deprecated names * Old, deprecated names
*/ */
#ifdef TTY_GRAPHICS #ifdef TTY_GRAPHICS
#define eight_bit_tty wc_eight_bit_input #define eight_bit_tty wc_eight_bit_input
+10
View File
@@ -22,6 +22,7 @@
#define MOUSECMD 0x0800 /* cmd allowed to be bound to mouse button */ #define MOUSECMD 0x0800 /* cmd allowed to be bound to mouse button */
#define CMD_INSANE 0x1000 /* suppress sanity check (for ^P and ^R) */ #define CMD_INSANE 0x1000 /* suppress sanity check (for ^P and ^R) */
#define AUTOCOMP_ADJ 0x2000 /* user changed command autocompletion */ #define AUTOCOMP_ADJ 0x2000 /* user changed command autocompletion */
#define CMD_PARAM 0x4000 /* command requires a param from key bind */
/* flags for extcmds_match() */ /* flags for extcmds_match() */
#define ECM_NOFLAGS 0 #define ECM_NOFLAGS 0
@@ -29,6 +30,15 @@
#define ECM_EXACTMATCH 0x02 /* needs exact match of findstr */ #define ECM_EXACTMATCH 0x02 /* needs exact match of findstr */
#define ECM_NO1CHARCMD 0x04 /* ignore commands like '?' and '#' */ #define ECM_NO1CHARCMD 0x04 /* ignore commands like '?' and '#' */
/* a key bound to ext_func_tab */
struct Cmd_bind {
uchar key;
boolean userbind; /* added by user */
char *param;
const struct ext_func_tab *cmd;
struct Cmd_bind *next;
};
struct ext_func_tab { struct ext_func_tab {
uchar key; uchar key;
const char *ef_txt, *ef_desc; const char *ef_txt, *ef_desc;
+44 -3
View File
@@ -102,18 +102,20 @@ typedef unsigned readLenType;
#endif #endif
#define BOOL_RANDOM (-1) #define BOOL_RANDOM (-1)
enum optchoice { opt_in, opt_out};
/* /*
* type nhsym: loadable symbols go into this type * type nhsym: loadable symbols go into this type
*/ */
typedef uchar nhsym; typedef uchar nhsym;
#ifndef STRNCMPI #ifndef STRNCMPI
#ifndef __SASC_60 /* SAS/C already shifts to stricmp */ /* SAS/C already shifts to stricmp */
#if !defined(__SASC_60) && !defined(CROSS_TO_AMIGA)
#define strcmpi(a, b) strncmpi((a), (b), -1) #define strcmpi(a, b) strncmpi((a), (b), -1)
#endif #endif
#endif #endif
#ifdef CROSS_TO_AMIGA
#define strcmpi(a, b) stricmp(a, b)
#endif
/* #define SPECIALIZATION */ /* do "specialized" version of new topology */ /* #define SPECIALIZATION */ /* do "specialized" version of new topology */
@@ -571,6 +573,45 @@ typedef enum NHL_pcall_action {
NHLpa_impossible NHLpa_impossible
} NHL_pcall_action; } NHL_pcall_action;
enum optchoice { opt_in, opt_out};
/*
* option setting restrictions
*/
enum optset_restrictions {
set_in_sysconf = 0, /* system config file option only */
set_in_config = 1, /* config file option only */
set_viaprog = 2, /* may be set via extern program, not seen in game */
set_gameview = 3, /* may be set via extern program, displayed in game */
set_in_game = 4, /* may be set via extern program or set in the game */
set_wizonly = 5, /* may be set in the game if wizmode */
set_wiznofuz = 6, /* wizard-mode only, but not by fuzzer */
set_hidden = 7 /* placeholder for prefixed entries, never show it */
};
/* these aren't the same as set_xxx */
enum option_phases {
phase_not_set = 0,
builtin_opt = 1, /* compiled-in default value of an option */
syscf_opt, /* sysconf setting of an option, overrides builtin */
rc_file_opt, /* player's run-time config file setting, overrides syscf */
environ_opt, /* player's environment NETHACKOPTIONS, overrides rc_file */
cmdline_opt, /* program invocation command-line, overrides environ */
play_opt, /* 'O' command, interactively set so overrides all */
num_opt_phases
};
#define SET__IS_VALUE_VALID(s) ((s < set_in_sysconf) || (s > set_wiznofuz))
#include "optlist.h"
enum opt {
opt_prefix_only = -1,
#define NHOPT_ENUM
#include "optlist.h"
#undef NHOPT_ENUM
OPTCOUNT
};
#define SFCTOOL_BIT (1UL << 30) #define SFCTOOL_BIT (1UL << 30)
#endif /* GLOBAL_H */ #endif /* GLOBAL_H */
+10 -20
View File
@@ -252,7 +252,7 @@ struct cmd {
boolean swap_yz; /* QWERTZ keyboards; use z to move NW, y to zap */ boolean swap_yz; /* QWERTZ keyboards; use z to move NW, y to zap */
const char *dirchars; /* current movement/direction characters */ const char *dirchars; /* current movement/direction characters */
const char *alphadirchars; /* same as dirchars if !numpad */ const char *alphadirchars; /* same as dirchars if !numpad */
const struct ext_func_tab *commands[256]; /* indexed by input character */ struct Cmd_bind *cmdbinds;
const struct ext_func_tab *mousebtn[NUM_MOUSE_BUTTONS]; const struct ext_func_tab *mousebtn[NUM_MOUSE_BUTTONS];
char spkeys[NUM_NHKF]; char spkeys[NUM_NHKF];
char extcmd_char; /* key that starts an extended command ('#') */ char extcmd_char; /* key that starts an extended command ('#') */
@@ -571,6 +571,11 @@ enum hunger_state_types {
STARVED = 6 STARVED = 6
}; };
/* fake inventory letters, not 'a'..'z' or 'A'..'Z' */
#define NOINVSYM '#' /* overflow because all 52 letters are in use */
#define CONTAINED_SYM '>' /* designator for inside a container */
#define HANDS_SYM '-' /* hands|fingers|self depending on context */
/* inventory counts (slots in tty parlance) /* inventory counts (slots in tty parlance)
* a...zA..Z invlet_basic (52) * a...zA..Z invlet_basic (52)
* $a...zA..Z# 2 special additions * $a...zA..Z# 2 special additions
@@ -697,22 +702,6 @@ enum nhcb_calls {
NUM_NHCB NUM_NHCB
}; };
/*
* option setting restrictions
*/
enum optset_restrictions {
set_in_sysconf = 0, /* system config file option only */
set_in_config = 1, /* config file option only */
set_viaprog = 2, /* may be set via extern program, not seen in game */
set_gameview = 3, /* may be set via extern program, displayed in game */
set_in_game = 4, /* may be set via extern program or set in the game */
set_wizonly = 5, /* may be set in the game if wizmode */
set_wiznofuz = 6, /* wizard-mode only, but not by fuzzer */
set_hidden = 7 /* placeholder for prefixed entries, never show it */
};
#define SET__IS_VALUE_VALID(s) ((s < set_in_sysconf) || (s > set_wiznofuz))
struct plinemsg_type { struct plinemsg_type {
xint16 msgtype; /* one of MSGTYP_foo */ xint16 msgtype; /* one of MSGTYP_foo */
struct nhregex *regex; struct nhregex *regex;
@@ -776,7 +765,7 @@ struct selectionvar {
/* structure for 'program_state'; not saved and restored */ /* structure for 'program_state'; not saved and restored */
struct sinfo { struct sinfo {
int gameover; /* self explanatory? */ int gameover; /* self-explanatory? */
int stopprint; /* inhibit further end of game disclosure */ int stopprint; /* inhibit further end of game disclosure */
#ifdef HANGUPHANDLING #ifdef HANGUPHANDLING
volatile int done_hup; /* SIGHUP or moral equivalent received volatile int done_hup; /* SIGHUP or moral equivalent received
@@ -812,6 +801,7 @@ struct sinfo {
interface to suppress menu commands in similar conditions; interface to suppress menu commands in similar conditions;
readchar() always resets it to 'otherInp' prior to returning */ readchar() always resets it to 'otherInp' prior to returning */
int input_state; /* whether next key pressed will be entering a command */ int input_state; /* whether next key pressed will be entering a command */
int early_options; /* inside early_options processing */
#ifdef TTY_GRAPHICS #ifdef TTY_GRAPHICS
/* resize_pending only matters when handling a SIGWINCH signal for tty; /* resize_pending only matters when handling a SIGWINCH signal for tty;
getting_char is used along with that and also separately for UNIX; getting_char is used along with that and also separately for UNIX;
@@ -1345,7 +1335,7 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
/* Macros for launching objects */ /* Macros for launching objects */
#define ROLL 0x01 /* the object is rolling */ #define ROLL 0x01 /* the object is rolling */
#define FLING 0x02 /* the object is flying thru the air */ #define FLING 0x02 /* the object is flying through the air */
#define LAUNCH_UNSEEN 0x40 /* hero neither caused nor saw it */ #define LAUNCH_UNSEEN 0x40 /* hero neither caused nor saw it */
#define LAUNCH_KNOWN 0x80 /* the hero caused this by explicit action */ #define LAUNCH_KNOWN 0x80 /* the hero caused this by explicit action */
@@ -1527,7 +1517,7 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */
(objects[(obj)->otyp].a_ac + (obj)->spe \ (objects[(obj)->otyp].a_ac + (obj)->spe \
- min((int) greatest_erosion(obj), objects[(obj)->otyp].a_ac)) - min((int) greatest_erosion(obj), objects[(obj)->otyp].a_ac))
#define makeknown(x) discover_object((x), TRUE, TRUE) #define makeknown(x) discover_object((x), TRUE, TRUE, TRUE)
#define distu(xx, yy) dist2((coordxy) (xx), (coordxy) (yy), u.ux, u.uy) #define distu(xx, yy) dist2((coordxy) (xx), (coordxy) (yy), u.ux, u.uy)
#define mdistu(mon) distu((mon)->mx, (mon)->my) #define mdistu(mon) distu((mon)->mx, (mon)->my)
#define onlineu(xx, yy) online2((coordxy)(xx), (coordxy)(yy), u.ux, u.uy) #define onlineu(xx, yy) online2((coordxy)(xx), (coordxy)(yy), u.ux, u.uy)
+39
View File
@@ -0,0 +1,39 @@
#define MCF_NONE 0x0000
#define MCF_INDIRECT 0x0001 /* untargeted/indirect spell */
#define MCF_SIGHT 0x0002 /* monster needs to see hero */
#define MCF_HOSTILE 0x0004 /* cast by hostile monsters only */
#if defined(MCASTU_ENUM)
#define MONSPELL(def, lvl, flags) MCAST_##def
#elif defined(MCASTU_INIT)
#define MONSPELL(def, lvl, flags) { lvl, flags }
#elif defined(DUMP_MCASTU_ENUM1)
#define MONSPELL(def, lvl, flags) MCAST_DUMPENUM_##def
#elif defined(DUMP_MCASTU_ENUM2)
#define MONSPELL(def, lvl, flags) { MCAST_DUMPENUM_##def, #def }
#endif
MONSPELL(PSI_BOLT, 0, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(OPEN_WOUNDS, 0, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(CURE_SELF, 1, MCF_INDIRECT),
MONSPELL(HASTE_SELF, 2, MCF_INDIRECT),
MONSPELL(CONFUSE_YOU, 2, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(STUN_YOU, 3, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(DISAPPEAR, 4, MCF_INDIRECT),
MONSPELL(PARALYZE, 4, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(BLIND_YOU, 6, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(WEAKEN_YOU, 6, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(DESTRY_ARMR, 8, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(INSECTS, 8, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
MONSPELL(CURSE_ITEMS, 10, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(LIGHTNING, 11, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(FIRE_PILLAR, 12, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(GEYSER, 13, MCF_HOSTILE|MCF_SIGHT),
MONSPELL(AGGRAVATION, 13, MCF_INDIRECT|MCF_HOSTILE|MCF_SIGHT),
MONSPELL(SUMMON_MONS, 15, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
MONSPELL(CLONE_WIZ, 18, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
MONSPELL(DEATH_TOUCH, 20, MCF_HOSTILE|MCF_SIGHT),
#undef MONSPELL
+1
View File
@@ -98,6 +98,7 @@ struct epri {
schar shroom; /* index in rooms */ schar shroom; /* index in rooms */
coord shrpos; /* position of shrine */ coord shrpos; /* position of shrine */
d_level shrlevel; /* level (& dungeon) of shrine */ d_level shrlevel; /* level (& dungeon) of shrine */
unsigned cheapskate_count; /* number of cheapskate donations */
long intone_time, /* used to limit verbosity +*/ long intone_time, /* used to limit verbosity +*/
enter_time, /*+ of temple entry messages */ enter_time, /*+ of temple entry messages */
hostile_time, /* forbidding feeling */ hostile_time, /* forbidding feeling */
+8 -2
View File
@@ -18,9 +18,9 @@
#define UNLOCKDOOR 0x00800000L /* unlocks locked doors */ #define UNLOCKDOOR 0x00800000L /* unlocks locked doors */
#define BUSTDOOR 0x01000000L /* breaks any doors */ #define BUSTDOOR 0x01000000L /* breaks any doors */
#define ALLOW_ROCK 0x02000000L /* pushes rocks */ #define ALLOW_ROCK 0x02000000L /* pushes rocks */
#define ALLOW_WALL 0x04000000L /* walks thru walls */ #define ALLOW_WALL 0x04000000L /* walks through walls */
#define ALLOW_DIG 0x08000000L /* digs */ #define ALLOW_DIG 0x08000000L /* digs */
#define ALLOW_BARS 0x10000000L /* may pass thru iron bars */ #define ALLOW_BARS 0x10000000L /* may pass through iron bars */
#define ALLOW_SANCT 0x20000000L /* enters temples */ #define ALLOW_SANCT 0x20000000L /* enters temples */
#define ALLOW_SSM 0x40000000L /* ignores scare monster */ #define ALLOW_SSM 0x40000000L /* ignores scare monster */
#ifdef NHSTDC #ifdef NHSTDC
@@ -30,4 +30,10 @@
#endif #endif
/* clang-format on */ /* clang-format on */
struct mfndposdata {
int cnt;
coord poss[9];
long info[9];
};
#endif /* MFNDPOS_H */ #endif /* MFNDPOS_H */
+2 -2
View File
@@ -53,7 +53,7 @@
#define AD_BLND 11 /* blinds (yellow light) */ #define AD_BLND 11 /* blinds (yellow light) */
#define AD_STUN 12 /* stuns */ #define AD_STUN 12 /* stuns */
#define AD_SLOW 13 /* slows */ #define AD_SLOW 13 /* slows */
#define AD_PLYS 14 /* paralyses */ #define AD_PLYS 14 /* paralyzes */
#define AD_DRLI 15 /* drains life levels (Vampire) */ #define AD_DRLI 15 /* drains life levels (Vampire) */
#define AD_DREN 16 /* drains magic energy */ #define AD_DREN 16 /* drains magic energy */
#define AD_LEGS 17 /* damages legs (xan) */ #define AD_LEGS 17 /* damages legs (xan) */
@@ -101,7 +101,7 @@ struct mhitm_data {
}; };
/* /*
* Monster to monster attacks. When a monster attacks another (mattackm), * Monster-to-monster attacks. When a monster attacks another (mattackm),
* any or all of the following can be returned. See mattackm() for more * any or all of the following can be returned. See mattackm() for more
* details. * details.
*/ */
+1 -1
View File
@@ -173,7 +173,7 @@
as unique even though they really aren't; that's ok here */ as unique even though they really aren't; that's ok here */
#define unique_corpstat(ptr) (((ptr)->geno & G_UNIQ) != 0) #define unique_corpstat(ptr) (((ptr)->geno & G_UNIQ) != 0)
/* this returns the light's range, or 0 if none; if we add more light emitting /* this returns the light's range, or 0 if none; if we add more light-emitting
monsters, we'll likely have to add a new light range field to mons[] */ monsters, we'll likely have to add a new light range field to mons[] */
#define emits_light(ptr) \ #define emits_light(ptr) \
(((ptr)->mlet == S_LIGHT || (ptr) == &mons[PM_FLAMING_SPHERE] \ (((ptr)->mlet == S_LIGHT || (ptr) == &mons[PM_FLAMING_SPHERE] \
+2 -2
View File
@@ -85,9 +85,9 @@ enum ms_sounds {
#define M1_FLY 0x00000001L /* can fly or float */ #define M1_FLY 0x00000001L /* can fly or float */
#define M1_SWIM 0x00000002L /* can traverse water */ #define M1_SWIM 0x00000002L /* can traverse water */
#define M1_AMORPHOUS 0x00000004L /* can flow under doors */ #define M1_AMORPHOUS 0x00000004L /* can flow under doors */
#define M1_WALLWALK 0x00000008L /* can phase thru rock */ #define M1_WALLWALK 0x00000008L /* can phase through rock */
#define M1_CLING 0x00000010L /* can cling to ceiling */ #define M1_CLING 0x00000010L /* can cling to ceiling */
#define M1_TUNNEL 0x00000020L /* can tunnel thru rock */ #define M1_TUNNEL 0x00000020L /* can tunnel through rock */
#define M1_NEEDPICK 0x00000040L /* needs pick to tunnel */ #define M1_NEEDPICK 0x00000040L /* needs pick to tunnel */
#define M1_CONCEAL 0x00000080L /* hides under objects */ #define M1_CONCEAL 0x00000080L /* hides under objects */
#define M1_HIDE 0x00000100L /* mimics, blends in with ceiling */ #define M1_HIDE 0x00000100L /* mimics, blends in with ceiling */
+3
View File
@@ -162,6 +162,9 @@ struct monst {
Bitfield(meverseen, 1); /* mon has been seen at some point */ Bitfield(meverseen, 1); /* mon has been seen at some point */
Bitfield(mspotted, 1); /* mon is currently seen by hero */ Bitfield(mspotted, 1); /* mon is currently seen by hero */
Bitfield(mwandexp, 1); /* mon has experience with wands */
Bitfield(mgenmklev, 1); /* made by the level generation */
/* 5 spare bits */
unsigned long mstrategy; /* for monsters with mflag3: current strategy */ unsigned long mstrategy; /* for monsters with mflag3: current strategy */
#ifdef NHSTDC #ifdef NHSTDC
+5 -5
View File
@@ -1600,7 +1600,7 @@
M2_STRONG | M2_NEUTER, 0, M2_STRONG | M2_NEUTER, 0,
10, CLR_BROWN, EARTH_ELEMENTAL), 10, CLR_BROWN, EARTH_ELEMENTAL),
MON(NAM("water elemental"), S_ELEMENTAL, MON(NAM("water elemental"), S_ELEMENTAL,
LVL(8, 6, 2, 30, 0), (G_NOCORPSE | 1), LVL(8, 5, 2, 30, 0), (G_NOCORPSE | 1),
A(ATTK(AT_CLAW, AD_PHYS, 5, 6), A(ATTK(AT_CLAW, AD_PHYS, 5, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(2500, 0, MS_SILENT, MZ_HUGE), MR_POISON | MR_STONE, 0, SIZ(2500, 0, MS_SILENT, MZ_HUGE), MR_POISON | MR_STONE, 0,
@@ -3395,8 +3395,8 @@
/* monster priests are separate monsters (above; "aligned cleric") */ /* monster priests are separate monsters (above; "aligned cleric") */
MON(NAMS("priest", "priestess", "cleric"), S_HUMAN, MON(NAMS("priest", "priestess", "cleric"), S_HUMAN,
LVL(10, 12, 10, 2, 0), G_NOGEN, LVL(10, 12, 10, 2, 0), G_NOGEN,
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_CLRC, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0, SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE, M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT, M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT,
@@ -3451,8 +3451,8 @@
12, HI_DOMESTIC, VALKYRIE), 12, HI_DOMESTIC, VALKYRIE),
MON(NAM("wizard"), S_HUMAN, MON(NAM("wizard"), S_HUMAN,
LVL(10, 12, 10, 3, 0), G_NOGEN, LVL(10, 12, 10, 3, 0), G_NOGEN,
A(ATTK(AT_WEAP, AD_PHYS, 1, 6), A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0, SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
M1_HUMANOID | M1_OMNIVORE, M1_HUMANOID | M1_OMNIVORE,
M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT | M2_MAGIC, M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT | M2_MAGIC,
+4 -1
View File
@@ -107,7 +107,9 @@ struct obj {
* or enchantment); many items have this preset if * or enchantment); many items have this preset if
* they lack anything interesting to discover */ * they lack anything interesting to discover */
Bitfield(dknown, 1); /* description known (item seen "up close"); Bitfield(dknown, 1); /* description known (item seen "up close");
* some types of items always have dknown set */ * some types of items always have dknown set;
* use observe_object to set to TRUE so that the
* discoveries list is still correct */
Bitfield(bknown, 1); /* BUC (blessed/uncursed/cursed) known */ Bitfield(bknown, 1); /* BUC (blessed/uncursed/cursed) known */
Bitfield(rknown, 1); /* rustproofing status known */ Bitfield(rknown, 1); /* rustproofing status known */
Bitfield(cknown, 1); /* for containers (including statues): the contents Bitfield(cknown, 1); /* for containers (including statues): the contents
@@ -449,6 +451,7 @@ struct obj {
#define BURIED_TOO 0x2 #define BURIED_TOO 0x2
/* object erosion types */ /* object erosion types */
#define ERODE_NONE -1
#define ERODE_BURN 0 #define ERODE_BURN 0
#define ERODE_RUST 1 #define ERODE_RUST 1
#define ERODE_ROT 2 #define ERODE_ROT 2
+12 -7
View File
@@ -54,8 +54,8 @@ struct objclass {
* otherwise, obj->dknown and obj->bknown * otherwise, obj->dknown and obj->bknown
* tell all, and obj->known should always * tell all, and obj->known should always
* be set for proper merging behavior. */ * be set for proper merging behavior. */
Bitfield(oc_pre_discovered, 1); /* already known at start of game; flagged Bitfield(oc_encountered, 1); /* hero has observed such an item at least
* as such when discoveries are listed */ once (perhaps without naming it) */
Bitfield(oc_magic, 1); /* inherently magical object */ Bitfield(oc_magic, 1); /* inherently magical object */
Bitfield(oc_charged, 1); /* may have +n or (n) charges */ Bitfield(oc_charged, 1); /* may have +n or (n) charges */
Bitfield(oc_unique, 1); /* special one-of-a-kind object */ Bitfield(oc_unique, 1); /* special one-of-a-kind object */
@@ -76,9 +76,9 @@ struct objclass {
#define IMMEDIATE 2 /* directional beam that doesn't ricochet */ #define IMMEDIATE 2 /* directional beam that doesn't ricochet */
#define RAY 3 /* beam that does bounce off walls */ #define RAY 3 /* beam that does bounce off walls */
/* overloaded oc_dir: strike mode bit mask for weapons and weptools */ /* overloaded oc_dir: strike mode bit mask for weapons and weptools */
#define PIERCE 01 /* pointed weapon punctures target */ #define PIERCE 1 /* pointed weapon punctures target */
#define SLASH 02 /* sharp weapon cuts target */ #define SLASH 2 /* sharp weapon cuts target */
#define WHACK 04 /* blunt weapon bashes target */ #define WHACK 4 /* blunt weapon bashes target */
Bitfield(oc_material, 5); /* one of obj_material_types */ Bitfield(oc_material, 5); /* one of obj_material_types */
schar oc_subtyp; schar oc_subtyp;
@@ -91,7 +91,7 @@ struct objclass {
uchar oc_color; /* color of the object */ uchar oc_color; /* color of the object */
short oc_prob; /* probability, used in mkobj() */ short oc_prob; /* probability, used in mkobj() */
unsigned short oc_weight; /* encumbrance (1 cn = 0.1 lb.) */ unsigned oc_weight; /* encumbrance (1 cn = 0.1 lb.) */
short oc_cost; /* base cost in shops */ short oc_cost; /* base cost in shops */
/* Check the AD&D rules! The FIRST is small monster damage. */ /* Check the AD&D rules! The FIRST is small monster damage. */
/* for weapons, and tools, rocks, and gems useful as weapons */ /* for weapons, and tools, rocks, and gems useful as weapons */
@@ -104,6 +104,11 @@ struct objclass {
#define oc_level oc_oc2 /* books: spell level */ #define oc_level oc_oc2 /* books: spell level */
unsigned short oc_nutrition; /* food value */ unsigned short oc_nutrition; /* food value */
unsigned long oc_sell_minseen;
unsigned long oc_sell_maxseen;
unsigned long oc_buy_minseen;
unsigned long oc_buy_maxseen;
}; };
struct class_sym { struct class_sym {
@@ -146,7 +151,7 @@ enum objclass_syms {
/* for mkobj() use ONLY! odd '-SPBOOK_CLASS' is in case of unsigned enums */ /* for mkobj() use ONLY! odd '-SPBOOK_CLASS' is in case of unsigned enums */
#define SPBOOK_no_NOVEL (0 - (int) SPBOOK_CLASS) #define SPBOOK_no_NOVEL (0 - (int) SPBOOK_CLASS)
#define BURNING_OIL (MAXOCLASSES + 1) /* Can be used as input to explode. */ #define BURNING_OIL (MAXOCLASSES + 1) /* Can be used as input to explode */
#define MON_EXPLODE (MAXOCLASSES + 2) /* Exploding monster (e.g. gas spore) */ #define MON_EXPLODE (MAXOCLASSES + 2) /* Exploding monster (e.g. gas spore) */
#define TRAP_EXPLODE (MAXOCLASSES + 3) #define TRAP_EXPLODE (MAXOCLASSES + 3)
+49 -37
View File
@@ -41,10 +41,14 @@
the second zero is oc_spare1 for padding between oc_tough and oc_dir */ the second zero is oc_spare1 for padding between oc_tough and oc_dir */
#define BITS(nmkn,mrg,uskn,ctnr,mgc,chrg,uniq,nwsh,big,tuf,dir,sub,mtrl) \ #define BITS(nmkn,mrg,uskn,ctnr,mgc,chrg,uniq,nwsh,big,tuf,dir,sub,mtrl) \
nmkn,mrg,uskn,0,mgc,chrg,uniq,nwsh,big,tuf,0,dir,mtrl,sub /*cpp fodder*/ nmkn,mrg,uskn,0,mgc,chrg,uniq,nwsh,big,tuf,0,dir,mtrl,sub /*cpp fodder*/
/* note: 0UL-1UL is a method of expressing the largest possible
unsigned long value whilst working around a false-positive warning
in Microsoft Visual C (which assumes that a negative number was
intended despite the explicit U suffix) */
#define OBJECT(obj,bits,prp,sym,prob,dly,wt, \ #define OBJECT(obj,bits,prp,sym,prob,dly,wt, \
cost,sdam,ldam,oc1,oc2,nut,color,sn) \ cost,sdam,ldam,oc1,oc2,nut,color,sn) \
{ 0, 0, (char *) 0, bits, prp, sym, dly, color, prob, wt, \ { 0, 0, (char *) 0, bits, prp, sym, dly, color, prob, wt, \
cost, sdam, ldam, oc1, oc2, nut } cost, sdam, ldam, oc1, oc2, nut, (0UL-1UL), 0, (0UL-1UL), 0 }
#define MARKER(tag,sn) /*empty*/ #define MARKER(tag,sn) /*empty*/
#elif defined(OBJECTS_ENUM) #elif defined(OBJECTS_ENUM)
@@ -451,12 +455,12 @@ HELM("fedora", NoDes,
1, 0, 0, 0, 0, 3, 1, 10, 0, CLOTH, CLR_BROWN, 1, 0, 0, 0, 0, 3, 1, 10, 0, CLOTH, CLR_BROWN,
FEDORA), FEDORA),
HELM("cornuthaum", "conical hat", HELM("cornuthaum", "conical hat",
0, 1, CLAIRVOYANT, 3, 1, 4, 80, 10, 1, CLOTH, CLR_BLUE, 0, 1, CLAIRVOYANT, 5, 1, 4, 80, 10, 1, CLOTH, CLR_BLUE,
/* name coined by devteam; confers clairvoyance for wizards, /* name coined by devteam; confers clairvoyance for wizards,
blocks clairvoyance if worn by role other than wizard */ blocks clairvoyance if worn by role other than wizard */
CORNUTHAUM), CORNUTHAUM),
HELM("dunce cap", "conical hat", HELM("dunce cap", "conical hat",
0, 1, 0, 3, 1, 4, 1, 10, 0, CLOTH, CLR_BLUE, 0, 1, 0, 5, 1, 4, 1, 10, 0, CLOTH, CLR_BLUE,
/* sets Int and Wis to fixed value of 6, so actually provides /* sets Int and Wis to fixed value of 6, so actually provides
protection against death caused by Int being drained below 3 */ protection against death caused by Int being drained below 3 */
DUNCE_CAP), DUNCE_CAP),
@@ -464,7 +468,7 @@ HELM("dented pot", NoDes,
1, 0, 0, 2, 0, 10, 8, 9, 0, IRON, CLR_BLACK, 1, 0, 0, 2, 0, 10, 8, 9, 0, IRON, CLR_BLACK,
DENTED_POT), DENTED_POT),
HELM("helm of brilliance", "crystal helmet", HELM("helm of brilliance", "crystal helmet",
0, 1, 0, 3, 1, 40, 50, 9, 0, GLASS, CLR_WHITE, 0, 1, 0, 6, 1, 40, 50, 9, 0, GLASS, CLR_WHITE,
/* used to be iron and shuffled as "etched helmet" but required /* used to be iron and shuffled as "etched helmet" but required
special case for the effect of iron armor on spell casting */ special case for the effect of iron armor on spell casting */
HELM_OF_BRILLIANCE), HELM_OF_BRILLIANCE),
@@ -473,13 +477,13 @@ HELM("helmet", "plumed helmet",
0, 0, 0, 10, 1, 30, 10, 9, 0, IRON, HI_METAL, 0, 0, 0, 10, 1, 30, 10, 9, 0, IRON, HI_METAL,
HELMET), HELMET),
HELM("helm of caution", "etched helmet", HELM("helm of caution", "etched helmet",
0, 1, WARNING, 3, 1, 50, 50, 9, 0, IRON, CLR_GREEN, 0, 1, WARNING, 6, 1, 50, 50, 9, 0, IRON, CLR_GREEN,
HELM_OF_CAUTION), HELM_OF_CAUTION),
HELM("helm of opposite alignment", "crested helmet", HELM("helm of opposite alignment", "crested helmet",
0, 1, 0, 6, 1, 50, 50, 9, 0, IRON, HI_METAL, 0, 1, 0, 10, 1, 50, 50, 9, 0, IRON, HI_METAL,
HELM_OF_OPPOSITE_ALIGNMENT), HELM_OF_OPPOSITE_ALIGNMENT),
HELM("helm of telepathy", "visored helmet", HELM("helm of telepathy", "visored helmet",
0, 1, TELEPAT, 2, 1, 50, 50, 9, 0, IRON, HI_METAL, 0, 1, TELEPAT, 4, 1, 50, 50, 9, 0, IRON, HI_METAL,
HELM_OF_TELEPATHY), HELM_OF_TELEPATHY),
/* suits of armor */ /* suits of armor */
@@ -550,19 +554,19 @@ DRGN_ARMR("yellow dragon scales", 0, ACID_RES, 500, 7, CLR_YELLOW,
#undef DRGN_ARMR #undef DRGN_ARMR
/* other suits */ /* other suits */
ARMOR("plate mail", NoDes, ARMOR("plate mail", NoDes,
1, 0, 1, 0, 44, 5, 450, 600, 3, 2, ARM_SUIT, IRON, HI_METAL, 1, 0, 1, 0, 40, 5, 450, 600, 3, 2, ARM_SUIT, IRON, HI_METAL,
PLATE_MAIL), PLATE_MAIL),
ARMOR("crystal plate mail", NoDes, ARMOR("crystal plate mail", NoDes,
1, 0, 1, 0, 10, 5, 415, 820, 3, 2, ARM_SUIT, GLASS, CLR_WHITE, 1, 0, 1, 0, 10, 5, 415, 820, 3, 2, ARM_SUIT, GLASS, CLR_WHITE,
CRYSTAL_PLATE_MAIL), CRYSTAL_PLATE_MAIL),
ARMOR("bronze plate mail", NoDes, ARMOR("bronze plate mail", NoDes,
1, 0, 1, 0, 25, 5, 450, 400, 4, 1, ARM_SUIT, COPPER, HI_COPPER, 1, 0, 1, 0, 23, 5, 450, 400, 4, 1, ARM_SUIT, COPPER, HI_COPPER,
BRONZE_PLATE_MAIL), BRONZE_PLATE_MAIL),
ARMOR("splint mail", NoDes, ARMOR("splint mail", NoDes,
1, 0, 1, 0, 62, 5, 400, 80, 4, 1, ARM_SUIT, IRON, HI_METAL, 1, 0, 1, 0, 57, 5, 400, 80, 4, 1, ARM_SUIT, IRON, HI_METAL,
SPLINT_MAIL), SPLINT_MAIL),
ARMOR("banded mail", NoDes, ARMOR("banded mail", NoDes,
1, 0, 1, 0, 72, 5, 350, 90, 4, 1, ARM_SUIT, IRON, HI_METAL, 1, 0, 1, 0, 66, 5, 350, 90, 4, 1, ARM_SUIT, IRON, HI_METAL,
BANDED_MAIL), BANDED_MAIL),
ARMOR("dwarvish mithril-coat", NoDes, ARMOR("dwarvish mithril-coat", NoDes,
1, 0, 0, 0, 10, 1, 150, 240, 4, 2, ARM_SUIT, MITHRIL, HI_SILVER, 1, 0, 0, 0, 10, 1, 150, 240, 4, 2, ARM_SUIT, MITHRIL, HI_SILVER,
@@ -571,28 +575,28 @@ ARMOR("elven mithril-coat", NoDes,
1, 0, 0, 0, 15, 1, 150, 240, 5, 2, ARM_SUIT, MITHRIL, HI_SILVER, 1, 0, 0, 0, 15, 1, 150, 240, 5, 2, ARM_SUIT, MITHRIL, HI_SILVER,
ELVEN_MITHRIL_COAT), ELVEN_MITHRIL_COAT),
ARMOR("chain mail", NoDes, ARMOR("chain mail", NoDes,
1, 0, 0, 0, 72, 5, 300, 75, 5, 1, ARM_SUIT, IRON, HI_METAL, 1, 0, 0, 0, 66, 5, 300, 75, 5, 1, ARM_SUIT, IRON, HI_METAL,
CHAIN_MAIL), CHAIN_MAIL),
ARMOR("orcish chain mail", "crude chain mail", ARMOR("orcish chain mail", "crude chain mail",
0, 0, 0, 0, 20, 5, 300, 75, 6, 1, ARM_SUIT, IRON, CLR_BLACK, 0, 0, 0, 0, 19, 5, 300, 75, 6, 1, ARM_SUIT, IRON, CLR_BLACK,
ORCISH_CHAIN_MAIL), ORCISH_CHAIN_MAIL),
ARMOR("scale mail", NoDes, ARMOR("scale mail", NoDes,
1, 0, 0, 0, 72, 5, 250, 45, 6, 1, ARM_SUIT, IRON, HI_METAL, 1, 0, 0, 0, 66, 5, 250, 45, 6, 1, ARM_SUIT, IRON, HI_METAL,
SCALE_MAIL), SCALE_MAIL),
ARMOR("studded leather armor", NoDes, ARMOR("studded leather armor", NoDes,
1, 0, 0, 0, 72, 3, 200, 15, 7, 1, ARM_SUIT, LEATHER, HI_LEATHER, 1, 0, 0, 0, 66, 3, 200, 15, 7, 1, ARM_SUIT, LEATHER, HI_LEATHER,
STUDDED_LEATHER_ARMOR), STUDDED_LEATHER_ARMOR),
ARMOR("ring mail", NoDes, ARMOR("ring mail", NoDes,
1, 0, 0, 0, 72, 5, 250, 100, 7, 1, ARM_SUIT, IRON, HI_METAL, 1, 0, 0, 0, 66, 5, 250, 100, 7, 1, ARM_SUIT, IRON, HI_METAL,
RING_MAIL), RING_MAIL),
ARMOR("orcish ring mail", "crude ring mail", ARMOR("orcish ring mail", "crude ring mail",
0, 0, 0, 0, 20, 5, 250, 80, 8, 1, ARM_SUIT, IRON, CLR_BLACK, 0, 0, 0, 0, 19, 5, 250, 80, 8, 1, ARM_SUIT, IRON, CLR_BLACK,
ORCISH_RING_MAIL), ORCISH_RING_MAIL),
ARMOR("leather armor", NoDes, ARMOR("leather armor", NoDes,
1, 0, 0, 0, 82, 3, 150, 5, 8, 1, ARM_SUIT, LEATHER, HI_LEATHER, 1, 0, 0, 0, 75, 3, 150, 5, 8, 1, ARM_SUIT, LEATHER, HI_LEATHER,
LEATHER_ARMOR), LEATHER_ARMOR),
ARMOR("leather jacket", NoDes, ARMOR("leather jacket", NoDes,
1, 0, 0, 0, 12, 0, 30, 10, 9, 0, ARM_SUIT, LEATHER, CLR_BLACK, 1, 0, 0, 0, 11, 0, 30, 10, 9, 0, ARM_SUIT, LEATHER, CLR_BLACK,
LEATHER_JACKET), LEATHER_JACKET),
/* shirts */ /* shirts */
@@ -620,52 +624,58 @@ CLOAK("oilskin cloak", "slippery cloak",
0, 0, 0, 8, 0, 10, 50, 9, 2, CLOTH, HI_CLOTH, 0, 0, 0, 8, 0, 10, 50, 9, 2, CLOTH, HI_CLOTH,
OILSKIN_CLOAK), OILSKIN_CLOAK),
CLOAK("robe", NoDes, CLOAK("robe", NoDes,
1, 1, 0, 3, 0, 15, 50, 8, 2, CLOTH, CLR_RED, ROBE), 1, 1, 0, 6, 0, 15, 50, 8, 2, CLOTH, CLR_RED, ROBE),
/* robe was adopted from slash'em, where it's worn as a suit /* robe was adopted from slash'em, where it's worn as a suit
rather than as a cloak and there are several variations */ rather than as a cloak and there are several variations */
CLOAK("alchemy smock", "apron", CLOAK("alchemy smock", "apron",
0, 1, POISON_RES, 9, 0, 10, 50, 9, 1, CLOTH, CLR_WHITE, 0, 1, POISON_RES, 11, 0, 10, 50, 9, 1, CLOTH, CLR_WHITE,
ALCHEMY_SMOCK), ALCHEMY_SMOCK),
CLOAK("leather cloak", NoDes, CLOAK("leather cloak", NoDes,
1, 0, 0, 8, 0, 15, 40, 9, 1, LEATHER, CLR_BROWN, 1, 0, 0, 8, 0, 15, 40, 9, 1, LEATHER, CLR_BROWN,
LEATHER_CLOAK), LEATHER_CLOAK),
/* with shuffled appearances... */ /* with shuffled appearances... */
CLOAK("cloak of protection", "tattered cape", CLOAK("cloak of protection", "tattered cape",
0, 1, PROTECTION, 9, 0, 10, 50, 7, 3, CLOTH, HI_CLOTH, 0, 1, PROTECTION, 11, 0, 10, 50, 7, 3, CLOTH, HI_CLOTH,
CLOAK_OF_PROTECTION), CLOAK_OF_PROTECTION),
/* cloak of protection is now the only item conferring MC 3 */ /* cloak of protection is now the only item conferring MC 3 */
CLOAK("cloak of invisibility", "opera cloak", CLOAK("cloak of invisibility", "opera cloak",
0, 1, INVIS, 10, 0, 10, 60, 9, 1, CLOTH, CLR_BRIGHT_MAGENTA, 0, 1, INVIS, 12, 0, 10, 60, 9, 1, CLOTH, CLR_BRIGHT_MAGENTA,
CLOAK_OF_INVISIBILITY), CLOAK_OF_INVISIBILITY),
CLOAK("cloak of magic resistance", "ornamental cope", CLOAK("cloak of magic resistance", "ornamental cope",
0, 1, ANTIMAGIC, 2, 0, 10, 60, 9, 1, CLOTH, CLR_WHITE, 0, 1, ANTIMAGIC, 6, 0, 10, 60, 9, 1, CLOTH, CLR_WHITE,
CLOAK_OF_MAGIC_RESISTANCE), CLOAK_OF_MAGIC_RESISTANCE),
/* 'cope' is not a spelling mistake... leave it be */ /* 'cope' is not a spelling mistake... leave it be */
CLOAK("cloak of displacement", "piece of cloth", CLOAK("cloak of displacement", "piece of cloth",
0, 1, DISPLACED, 10, 0, 10, 50, 9, 1, CLOTH, HI_CLOTH, 0, 1, DISPLACED, 12, 0, 10, 50, 9, 1, CLOTH, HI_CLOTH,
CLOAK_OF_DISPLACEMENT), CLOAK_OF_DISPLACEMENT),
/* shields */ /* shields */
SHIELD("small shield", NoDes, SHIELD("small shield", "wooden shield",
1, 0, 0, 0, 6, 0, 30, 3, 9, 0, WOOD, HI_WOOD, 0, 0, 0, 0, 6, 0, 30, 3, 9, 0, WOOD, HI_WOOD,
SMALL_SHIELD), SMALL_SHIELD),
SHIELD("shield of drain resistance", "wooden shield",
0, 1, 0, DRAIN_RES, 12, 0, 30, 50, 9, 0, WOOD, HI_WOOD,
SHIELD_OF_DRAIN_RESISTANCE),
SHIELD("shield of shock resistance", "wooden shield",
0, 1, 0, SHOCK_RES, 12, 0, 30, 50, 9, 0, WOOD, HI_WOOD,
SHIELD_OF_SHOCK_RESISTANCE),
SHIELD("elven shield", "blue and green shield", SHIELD("elven shield", "blue and green shield",
0, 0, 0, 0, 2, 0, 40, 7, 8, 0, WOOD, CLR_GREEN, 0, 0, 0, 0, 2, 0, 40, 7, 8, 0, WOOD, CLR_GREEN,
ELVEN_SHIELD), ELVEN_SHIELD),
SHIELD("Uruk-hai shield", "white-handed shield", SHIELD("Uruk-hai shield", "white-handed shield",
0, 0, 0, 0, 2, 0, 50, 7, 9, 0, IRON, HI_METAL, 0, 0, 0, 0, 2, 0, 50, 7, 9, 0, IRON, HI_METAL,
URUK_HAI_SHIELD), URUK_HAI_SHIELD),
SHIELD("orcish shield", "red-eyed shield", SHIELD("orcish shield", "red-eyed shield",
0, 0, 0, 0, 2, 0, 50, 7, 9, 0, IRON, CLR_RED, 0, 0, 0, 0, 2, 0, 50, 7, 9, 0, IRON, CLR_RED,
ORCISH_SHIELD), ORCISH_SHIELD),
SHIELD("large shield", NoDes, SHIELD("large shield", NoDes,
1, 0, 1, 0, 7, 0, 100, 10, 8, 0, IRON, HI_METAL, 1, 0, 1, 0, 4, 0, 100, 10, 8, 0, IRON, HI_METAL,
LARGE_SHIELD), LARGE_SHIELD),
SHIELD("dwarvish roundshield", "large round shield", SHIELD("dwarvish roundshield", "large round shield",
0, 0, 0, 0, 4, 0, 100, 10, 8, 0, IRON, HI_METAL, 0, 0, 0, 0, 3, 0, 100, 10, 8, 0, IRON, HI_METAL,
DWARVISH_ROUNDSHIELD), DWARVISH_ROUNDSHIELD),
SHIELD("shield of reflection", "polished silver shield", SHIELD("shield of reflection", "polished silver shield",
0, 1, 0, REFLECTING, 3, 0, 50, 50, 8, 0, SILVER, HI_SILVER, 0, 1, 0, REFLECTING, 7, 0, 50, 50, 8, 0, SILVER, HI_SILVER,
SHIELD_OF_REFLECTION), SHIELD_OF_REFLECTION),
/* gloves */ /* gloves */
@@ -674,7 +684,7 @@ SHIELD("shield of reflection", "polished silver shield",
* HI_METAL or CLR_BLACK. All have shuffled descriptions. * HI_METAL or CLR_BLACK. All have shuffled descriptions.
*/ */
GLOVES("leather gloves", "old gloves", GLOVES("leather gloves", "old gloves",
0, 0, 0, 16, 1, 10, 8, 9, 0, LEATHER, HI_LEATHER, 0, 0, 0, 15, 1, 10, 8, 9, 0, LEATHER, HI_LEATHER,
LEATHER_GLOVES), LEATHER_GLOVES),
GLOVES("gauntlets of fumbling", "padded gloves", GLOVES("gauntlets of fumbling", "padded gloves",
0, 1, FUMBLING, 8, 1, 10, 50, 9, 0, LEATHER, HI_LEATHER, 0, 1, FUMBLING, 8, 1, 10, 50, 9, 0, LEATHER, HI_LEATHER,
@@ -688,11 +698,11 @@ GLOVES("gauntlets of dexterity", "fencing gloves",
/* boots */ /* boots */
BOOTS("low boots", "walking shoes", BOOTS("low boots", "walking shoes",
0, 0, 0, 25, 2, 10, 8, 9, 0, LEATHER, HI_LEATHER, LOW_BOOTS), 0, 0, 0, 23, 2, 10, 8, 9, 0, LEATHER, HI_LEATHER, LOW_BOOTS),
BOOTS("iron shoes", "hard shoes", BOOTS("iron shoes", "hard shoes",
0, 0, 0, 7, 2, 50, 16, 8, 0, IRON, HI_METAL, IRON_SHOES), 0, 0, 0, 7, 2, 50, 16, 8, 0, IRON, HI_METAL, IRON_SHOES),
BOOTS("high boots", "jackboots", BOOTS("high boots", "jackboots",
0, 0, 0, 15, 2, 20, 12, 8, 0, LEATHER, HI_LEATHER, HIGH_BOOTS), 0, 0, 0, 14, 2, 20, 12, 8, 0, LEATHER, HI_LEATHER, HIGH_BOOTS),
/* with shuffled appearances... */ /* with shuffled appearances... */
BOOTS("speed boots", "combat boots", BOOTS("speed boots", "combat boots",
0, 1, FAST, 12, 2, 20, 50, 9, 0, LEATHER, HI_LEATHER, SPEED_BOOTS), 0, 1, FAST, 12, 2, 20, 50, 9, 0, LEATHER, HI_LEATHER, SPEED_BOOTS),
@@ -1447,9 +1457,11 @@ WAND("create monster", "maple", 45, 200, 1, NODIR, WOOD, HI_WOOD,
WAN_CREATE_MONSTER), WAN_CREATE_MONSTER),
WAND("wishing", "pine", 5, 500, 1, NODIR, WOOD, HI_WOOD, WAND("wishing", "pine", 5, 500, 1, NODIR, WOOD, HI_WOOD,
WAN_WISHING), WAN_WISHING),
WAND("stasis", "redwood", 45, 150, 1, NODIR, WOOD, CLR_RED,
WAN_STASIS),
WAND("nothing", "oak", 25, 100, 0, IMMEDIATE, WOOD, HI_WOOD, WAND("nothing", "oak", 25, 100, 0, IMMEDIATE, WOOD, HI_WOOD,
WAN_NOTHING), WAN_NOTHING),
WAND("striking", "ebony", 75, 150, 1, IMMEDIATE, WOOD, HI_WOOD, WAND("striking", "ebony", 30, 150, 1, IMMEDIATE, WOOD, HI_WOOD,
WAN_STRIKING), WAN_STRIKING),
WAND("make invisible", "marble", 45, 150, 1, IMMEDIATE, MINERAL, HI_MINERAL, WAND("make invisible", "marble", 45, 150, 1, IMMEDIATE, MINERAL, HI_MINERAL,
WAN_MAKE_INVISIBLE), WAN_MAKE_INVISIBLE),
+15 -9
View File
@@ -4,10 +4,6 @@
#ifndef OPTLIST_H #ifndef OPTLIST_H
#define OPTLIST_H #define OPTLIST_H
#ifdef OPTIONS_C
static int optfn_boolean(int, int, boolean, char *, char *);
#endif
/* /*
* NOTE: If you add (or delete) an option, please review: * NOTE: If you add (or delete) an option, please review:
* doc/options.txt * doc/options.txt
@@ -16,6 +12,10 @@ static int optfn_boolean(int, int, boolean, char *, char *);
* updates that should accompany your change. * updates that should accompany your change.
*/ */
#define BACKWARD_COMPAT
extern int optfn_boolean(int, int, boolean, char *, char *);
enum OptType { BoolOpt, CompOpt, OthrOpt }; enum OptType { BoolOpt, CompOpt, OthrOpt };
enum Y_N { No, Yes }; enum Y_N { No, Yes };
enum Off_On { Off, On }; enum Off_On { Off, On };
@@ -45,7 +45,7 @@ struct allopt_t {
const char *alias; const char *alias;
const char *descr; const char *descr;
const char *prefixgw; const char *prefixgw;
boolean initval, has_handler, dupdetected; boolean initval, has_handler, dupdetected, disregarded;
}; };
#endif /* OPTLIST_H */ #endif /* OPTLIST_H */
@@ -74,16 +74,16 @@ static int optfn_##a(int, int, boolean, char *, char *);
#elif defined(NHOPT_PARSE) #elif defined(NHOPT_PARSE)
#define NHOPTB(a, sec, b, c, s, i, n, v, d, al, bp, termp, desc) \ #define NHOPTB(a, sec, b, c, s, i, n, v, d, al, bp, termp, desc) \
{ #a, OptS_##sec, 0, b, opt_##a, s, BoolOpt, n, v, d, No, termp, c, \ { #a, OptS_##sec, 0, b, opt_##a, s, BoolOpt, n, v, d, No, termp, c, \
bp, &optfn_boolean, al, desc, (const char *) 0, i, 0, 0 }, bp, &optfn_boolean, al, desc, (const char *) 0, i, 0, 0 , 0 },
#define NHOPTC(a, sec, b, c, s, n, v, d, h, al, z) \ #define NHOPTC(a, sec, b, c, s, n, v, d, h, al, z) \
{ #a, OptS_##sec, 0, b, opt_##a, s, CompOpt, n, v, d, No, 0, c, \ { #a, OptS_##sec, 0, b, opt_##a, s, CompOpt, n, v, d, No, 0, c, \
(boolean *) 0, &optfn_##a, al, z, (const char *) 0, Off, h, 0 }, (boolean *) 0, &optfn_##a, al, z, (const char *) 0, Off, h, 0, 0 },
#define NHOPTP(a, sec, b, c, s, n, v, d, h, al, z) \ #define NHOPTP(a, sec, b, c, s, n, v, d, h, al, z) \
{ #a, OptS_##sec, 0, b, pfx_##a, s, CompOpt, n, v, d, Yes, 0, c, \ { #a, OptS_##sec, 0, b, pfx_##a, s, CompOpt, n, v, d, Yes, 0, c, \
(boolean *) 0, &pfxfn_##a, al, z, #a, Off, h, 0 }, (boolean *) 0, &pfxfn_##a, al, z, #a, Off, h, 0, 0 },
#define NHOPTO(m, sec, a, b, c, s, n, v, d, al, z) \ #define NHOPTO(m, sec, a, b, c, s, n, v, d, al, z) \
{ m, OptS_##sec, 0, b, opt_##a, s, OthrOpt, n, v, d, No, 0, c, \ { m, OptS_##sec, 0, b, opt_##a, s, OthrOpt, n, v, d, No, 0, c, \
(boolean *) 0, &optfn_##a, al, z, (const char *) 0, On, On, 0 }, (boolean *) 0, &optfn_##a, al, z, (const char *) 0, On, On, 0, 0 },
/* this is not reliable because TILES_IN_GLYPHMAP might be defined /* this is not reliable because TILES_IN_GLYPHMAP might be defined
* in a multi-interface binary but not apply to the current interface */ * in a multi-interface binary but not apply to the current interface */
@@ -589,6 +589,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
NHOPTB(preload_tiles, Advanced, 0, opt_out, set_in_config, /* MSDOS only */ NHOPTB(preload_tiles, Advanced, 0, opt_out, set_in_config, /* MSDOS only */
On, Yes, No, No, NoAlias, &iflags.wc_preload_tiles, Term_False, On, Yes, No, No, NoAlias, &iflags.wc_preload_tiles, Term_False,
(char *)0) (char *)0)
NHOPTB(price_quotes, General, 0, opt_in, set_in_game,
Off, Yes, No, No, NoAlias, &iflags.pricequotes, Term_False,
"display prices you have seen for unidentified objects")
NHOPTB(pushweapon, Behavior, 0, opt_in, set_in_game, NHOPTB(pushweapon, Behavior, 0, opt_in, set_in_game,
Off, Yes, No, No, NoAlias, &flags.pushweapon, Term_False, Off, Yes, No, No, NoAlias, &flags.pushweapon, Term_False,
"previous weapon goes to secondary slot") "previous weapon goes to secondary slot")
@@ -608,6 +611,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
Off, No, No, No, NoAlias, (boolean *) 0, Term_False, Off, No, No, No, NoAlias, (boolean *) 0, Term_False,
(char *)0) (char *)0)
#endif #endif
NHOPTB(reroll, Advanced, 0, opt_in, set_in_config,
Off, Yes, No, No, NoAlias, &u.uroleplay.reroll, Term_False,
"allow rerolling of starting inventory and items")
NHOPTB(rest_on_space, Advanced, 0, opt_in, set_in_game, Off, NHOPTB(rest_on_space, Advanced, 0, opt_in, set_in_game, Off,
Yes, No, No, NoAlias, &flags.rest_on_space, Term_False, Yes, No, No, NoAlias, &flags.rest_on_space, Term_False,
"space bar is bound to the rest-command") "space bar is bound to the rest-command")
+2 -2
View File
@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones * Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files. * and save files.
*/ */
#define EDITLEVEL 130 #define EDITLEVEL 140
/* /*
* Development status possibilities. * Development status possibilities.
@@ -36,7 +36,7 @@
#define DEBUG #define DEBUG
#endif #endif
#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2025" #define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2026"
#define COPYRIGHT_BANNER_B \ #define COPYRIGHT_BANNER_B \
" By Stichting Mathematisch Centrum and M. Stephenson." " By Stichting Mathematisch Centrum and M. Stephenson."
/* nomakedefs.copyright_banner_c is generated at runtime */ /* nomakedefs.copyright_banner_c is generated at runtime */
+2 -2
View File
@@ -64,8 +64,8 @@ struct permonst {
aligntyp maligntyp; /* basic monster alignment */ aligntyp maligntyp; /* basic monster alignment */
unsigned short geno; /* creation/geno mask value */ unsigned short geno; /* creation/geno mask value */
struct attack mattk[NATTK]; /* attacks matrix */ struct attack mattk[NATTK]; /* attacks matrix */
unsigned short cwt, /* weight of corpse */ unsigned cwt; /* weight of corpse */
cnutrit; /* its nutritional value */ unsigned short cnutrit; /* its nutritional value */
uchar msound; /* noise it makes (6 bits) */ uchar msound; /* noise it makes (6 bits) */
uchar msize; /* physical size (3 bits) */ uchar msize; /* physical size (3 bits) */
uchar mresists; /* resistances */ uchar mresists; /* resistances */
+1 -1
View File
@@ -14,7 +14,7 @@ struct q_score { /* Quest "scorecard" */
Bitfield(killed_leader, 1); /* killed the quest leader */ Bitfield(killed_leader, 1); /* killed the quest leader */
Bitfield(first_locate, 1); /* only set the first time */ Bitfield(first_locate, 1); /* only set the first time */
Bitfield(met_intermed, 1); /* used if the locate is a person. */ Bitfield(met_intermed, 1); /* used if the locate is a person */
Bitfield(got_final, 1); /* got the final quest assignment */ Bitfield(got_final, 1); /* got the final quest assignment */
Bitfield(made_goal, 3); /* # of times on goal level */ Bitfield(made_goal, 3); /* # of times on goal level */
+1 -1
View File
@@ -56,7 +56,7 @@ typedef struct {
/* Should probably do the same thing about objects */ /* Should probably do the same thing about objects */
boolean visible; /* Is the region visible ? */ boolean visible; /* Is the region visible? */
int glyph; /* Which glyph to use if visible */ int glyph; /* Which glyph to use if visible */
anything arg; /* Optional user argument (Ex: strength of anything arg; /* Optional user argument (Ex: strength of
* force field, damage of a fire zone, ...*/ * force field, damage of a fire zone, ...*/
+4 -3
View File
@@ -12,8 +12,8 @@
* building on Don G Kneller's MS-DOS implementation. See drawing.c for * building on Don G Kneller's MS-DOS implementation. See drawing.c for
* the code that permits the user to set the contents of the symbol structure. * the code that permits the user to set the contents of the symbol structure.
* *
* The door representation was changed by Ari * The door representation was changed by
* Huttunen(ahuttune@niksula.hut.fi) * Ari Huttunen(ahuttune@niksula.hut.fi).
*/ */
/* /*
@@ -454,6 +454,7 @@ struct levelflags {
Bitfield(stormy, 1); /* clouds create lightning bolts at random */ Bitfield(stormy, 1); /* clouds create lightning bolts at random */
schar temperature; /* +1 == hot, -1 == cold */ schar temperature; /* +1 == hot, -1 == cold */
long stasis_until; /* wand of stasis effect lasts until when? */
}; };
typedef struct { typedef struct {
@@ -476,7 +477,7 @@ typedef struct {
#define fmon svl.level.monlist #define fmon svl.level.monlist
/* /*
* Covert a trap number into the defsym graphics array. * Convert a trap number into the defsym graphics array.
* Convert a defsym number into a trap number. * Convert a defsym number into a trap number.
* Assumes that arrow trap will always be the first trap. * Assumes that arrow trap will always be the first trap.
*/ */
+1
View File
@@ -145,6 +145,7 @@ typedef struct {
schar peaceful, asleep; schar peaceful, asleep;
short female, invis, cancelled, revived, avenge, fleeing, blinded, short female, invis, cancelled, revived, avenge, fleeing, blinded,
paralyzed, stunned, confused, waiting; paralyzed, stunned, confused, waiting;
short m_lev_adj;
long seentraps; long seentraps;
short has_invent; short has_invent;
mmflags_nht mm_flags; /* makemon flags */ mmflags_nht mm_flags; /* makemon flags */
+1 -1
View File
@@ -26,7 +26,7 @@ struct trap {
Bitfield(once, 1); Bitfield(once, 1);
Bitfield(madeby_u, 1); /* So monsters may take offence when you trap Bitfield(madeby_u, 1); /* So monsters may take offence when you trap
* them. Recognizing who made the trap isn't * them. Recognizing who made the trap isn't
* completely unreasonable, everybody has * completely unreasonable; everybody has
* their own style. This flag is also needed * their own style. This flag is also needed
* when you untrap a monster. It would be too * when you untrap a monster. It would be too
* easy to make a monster peaceful if you could * easy to make a monster peaceful if you could
+1
View File
@@ -22,6 +22,7 @@ typedef struct amii_mi {
char gselector; /* Group selector */ char gselector; /* Group selector */
char canselect; /* Can user select this entry. */ char canselect; /* Can user select this entry. */
char attr; /* Attribute for the line. */ char attr; /* Attribute for the line. */
int color; /* Color for the line (from menucolors). */
char *str; /* The text of the item. */ char *str; /* The text of the item. */
} amii_menu_item; } amii_menu_item;
-2
View File
@@ -26,8 +26,6 @@ extern WINDOW *activemenu; /* curses window for menu requesting a
#define SCROLLBAR_BACK_COLOR CLR_BLACK #define SCROLLBAR_BACK_COLOR CLR_BLACK
#define HIGHLIGHT_COLOR CLR_WHITE #define HIGHLIGHT_COLOR CLR_WHITE
#define MORECOLOR CLR_ORANGE #define MORECOLOR CLR_ORANGE
#define STAT_UP_COLOR CLR_GREEN
#define STAT_DOWN_COLOR CLR_RED
#define MESSAGE_WIN 1 #define MESSAGE_WIN 1
#define STATUS_WIN 2 #define STATUS_WIN 2
#define MAP_WIN 3 #define MAP_WIN 3
+3
View File
@@ -32,6 +32,9 @@
#define OPTIONS_AT_RUNTIME /* build info done at runtime not text file */ #define OPTIONS_AT_RUNTIME /* build info done at runtime not text file */
#define EARLY_CONFIGFILE_PASS
#define TTY_PERM_INVENT
/* /*
* ----------------------------------------------------------------- * -----------------------------------------------------------------
* The remaining code shouldn't need modification. * The remaining code shouldn't need modification.
+5 -77
View File
@@ -11,10 +11,13 @@
#endif #endif
enum wp_ids { wp_tty = 1, wp_X11, wp_Qt, wp_mswin, wp_curses, enum wp_ids { wp_tty = 1, wp_X11, wp_Qt, wp_mswin, wp_curses,
wp_chainin, wp_chainout, wp_safestartup, wp_shim, wp_chainin, wp_chainout, wp_shim,
wp_hup, wp_guistubs, wp_ttystubs, wp_hup, wp_guistubs, wp_ttystubs,
#if defined(AMIGA)
wp_amii, wp_amiv,
#endif
#ifdef OUTDATED_STUFF #ifdef OUTDATED_STUFF
wp_mac, wp_Gem, wp_Gnome, wp_amii, wp_amiv, wp_mac, wp_Gem, wp_Gnome,
#endif #endif
wp_trace // XXX do we need this? should chainin/out get an id? TBD wp_trace // XXX do we need this? should chainin/out get an id? TBD
}; };
@@ -412,79 +415,4 @@ struct chain_procs {
}; };
#endif /* WINCHAIN */ #endif /* WINCHAIN */
#ifdef SAFEPROCS
/*
* window port routines available in sys/share/safeproc.c
*/
extern struct window_procs *get_safe_procs(int);
extern void safe_init_nhwindows(int *, char **);
extern void safe_player_selection(void);
extern void safe_askname(void);
extern void safe_get_nh_event(void);
extern void safe_exit_nhwindows(const char *);
extern void safe_suspend_nhwindows(const char *);
extern void safe_resume_nhwindows(void);
extern winid safe_create_nhwindow(int);
extern void safe_clear_nhwindow(winid);
extern void safe_display_nhwindow(winid, boolean);
extern void safe_destroy_nhwindow(winid);
extern void safe_curs(winid, int, int);
extern void safe_putstr(winid, int, const char *);
extern void safe_putmixed(winid, int, const char *);
extern void safe_display_file(const char *, boolean);
extern void safe_start_menu(winid, unsigned long);
extern void safe_add_menu(winid, const glyph_info *, const ANY_P *,
char, char, int, int, const char *,
unsigned int);
extern void safe_end_menu(winid, const char *);
extern int safe_select_menu(winid, int, MENU_ITEM_P **);
extern char safe_message_menu(char, int, const char *);
extern void safe_mark_synch(void);
extern void safe_wait_synch(void);
#ifdef CLIPPING
extern void safe_cliparound(int, int);
#endif
#ifdef POSITIONBAR
extern void safe_update_positionbar(char *);
#endif
extern void safe_print_glyph(winid, coordxy, coordxy,
const glyph_info *, const glyph_info *);
extern void safe_raw_print(const char *);
extern void safe_raw_print_bold(const char *);
extern int safe_nhgetch(void);
extern int safe_nh_poskey(coordxy *, coordxy *, int *);
extern void safe_nhbell(void);
extern int safe_doprev_message(void);
extern char safe_yn_function(const char *, const char *, char);
extern void safe_getlin(const char *, char *);
extern int safe_get_ext_cmd(void);
extern void safe_number_pad(int);
extern void safe_delay_output(void);
#ifdef CHANGE_COLOR
extern void safe_change_color(int, long, int);
#ifdef MAC
extern void safe_change_background(int);
extern short safe_set_font_name(winid, char *);
#endif
extern char *safe_get_color_string(void);
#endif
extern void safe_outrip(winid, int, time_t);
extern void safe_preference_update(const char *);
extern char *safe_getmsghistory(boolean);
extern void safe_putmsghistory(const char *, boolean);
extern void safe_status_init(void);
extern void safe_status_finish(void);
extern void safe_status_enablefield(int, const char *, const char *,
boolean);
extern void safe_status_update(int, genericptr_t, int, int, int,
unsigned long *);
extern boolean safe_can_suspend(void);
extern void stdio_raw_print(const char *);
extern void stdio_nonl_raw_print(const char *);
extern void stdio_raw_print_bold(const char *);
extern void stdio_wait_synch(void);
extern void safe_update_inventory(int);
extern win_request_info *safe_ctrl_nhwindow(winid, int, win_request_info *);
extern int stdio_nhgetch(void);
#endif /* SAFEPROCS */
#endif /* WINPROCS_H */ #endif /* WINPROCS_H */
+8 -5
View File
@@ -163,11 +163,13 @@ struct u_conduct { /* number of times... */
}; };
struct u_roleplay { struct u_roleplay {
boolean blind; /* permanently blind */ boolean blind; /* permanently blind */
boolean nudist; /* has not worn any armor, ever */ boolean nudist; /* has not worn any armor, ever */
boolean deaf; /* permanently deaf */ boolean deaf; /* permanently deaf */
boolean pauper; /* no starting inventory */ boolean pauper; /* no starting inventory */
long numbones; /* # of bones files loaded */ boolean reroll; /* starting inventory/attr rerolling enabled */
long numbones; /* # of bones files loaded */
long numrerolls; /* # of rerolls used */
}; };
/*** Unified structure containing role information ***/ /*** Unified structure containing role information ***/
@@ -534,6 +536,7 @@ struct _hitmon_data {
boolean needpoismsg; boolean needpoismsg;
boolean poiskilled; boolean poiskilled;
boolean already_killed; boolean already_killed;
boolean offmap;
boolean destroyed; boolean destroyed;
boolean dryit; boolean dryit;
boolean doreturn; boolean doreturn;
+8 -8
View File
@@ -3,7 +3,7 @@ matrix:
include: include:
- name: linux-xenial-gcc-win-all - name: linux-xenial-gcc-win-all
os: linux os: linux
env: HINTS=linux.370 LUA_VERSION=5.4.6 env: HINTS=linux.370 LUA_VERSION=5.4.8
compiler: gcc compiler: gcc
addons: addons:
apt: apt:
@@ -21,7 +21,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install - make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-bionic-gcc-win-all - name: linux-bionic-gcc-win-all
os: linux os: linux
env: HINTS=linux.370 LUA_VERSION=5.4.6 env: HINTS=linux.370 LUA_VERSION=5.4.8
dist: bionic dist: bionic
compiler: gcc compiler: gcc
addons: addons:
@@ -40,7 +40,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install - make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-focal-clang-win-all - name: linux-focal-clang-win-all
os: linux os: linux
env: HINTS=linux.370 LUA_VERSION=5.4.6 env: HINTS=linux.370 LUA_VERSION=5.4.8
dist: focal dist: focal
compiler: clang compiler: clang
addons: addons:
@@ -59,7 +59,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install - make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-xenial-gcc-nocommon - name: linux-xenial-gcc-nocommon
os: linux os: linux
env: HINTS=linux.370 LUA_VERSION=5.4.6 env: HINTS=linux.370 LUA_VERSION=5.4.8
dist: xenial dist: xenial
compiler: gcc compiler: gcc
script: script:
@@ -70,7 +70,7 @@ matrix:
- make install - make install
- name: linux-focal-gcc9-win-all - name: linux-focal-gcc9-win-all
os: linux os: linux
env: HINTS=linux.370 LUA_VERSION=5.4.6 env: HINTS=linux.370 LUA_VERSION=5.4.8
dist: focal dist: focal
compiler: gcc compiler: gcc
addons: addons:
@@ -91,7 +91,7 @@ matrix:
- make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install - make LUA_VERSION=$LUA_VERSION WANT_WIN_ALL=1 QT_SELECT=5 MOC=moc install
- name: linux-xenial-gcc-minimal - name: linux-xenial-gcc-minimal
os: linux os: linux
env: HINTS=linux-minimal LUA_VERSION=5.4.6 env: HINTS=linux-minimal LUA_VERSION=5.4.8
compiler: gcc compiler: gcc
script: | script: |
cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../
@@ -128,7 +128,7 @@ matrix:
script: script:
- export ADD_CURSES=Y - export ADD_CURSES=Y
- export PDCURSES_TOP=../lib/pdcurses - export PDCURSES_TOP=../lib/pdcurses
- export LUA_VERSION=5.4.6 - export LUA_VERSION=5.4.8
- sh sys/windows/travis-gcc.sh - sh sys/windows/travis-gcc.sh
- test -d "lib/lua-$LUA_VERSION/src" || exit 0 - test -d "lib/lua-$LUA_VERSION/src" || exit 0
- test -d "lib/pdcurses" || exit 0 - test -d "lib/pdcurses" || exit 0
@@ -137,7 +137,7 @@ matrix:
- mingw32-make LUA_VERSION=$LUA_VERSION install - mingw32-make LUA_VERSION=$LUA_VERSION install
- name: msdos-linux-focal-djgpp-crosscompile - name: msdos-linux-focal-djgpp-crosscompile
os: linux os: linux
env: HINTS=linux.370 LUA_VERSION=5.4.6 env: HINTS=linux.370 LUA_VERSION=5.4.8
dist: focal dist: focal
compiler: gcc compiler: gcc
script: script:
@@ -24,9 +24,9 @@ endif
ifdef BUILD_TARGET_LUA ifdef BUILD_TARGET_LUA
#===============-================================================= #===============-=================================================
# LUA library # LUA library
# Source from http://www.lua.org/ftp/lua-5.4.6.tar.gz # Source from http://www.lua.org/ftp/lua-5.4.8.tar.gz
#================================================================= #=================================================================
LUA_VERSION ?=5.4.6 LUA_VERSION ?=5.4.8
LUATOP ?= ../lib/lua-$(LUA_VERSION) LUATOP ?= ../lib/lua-$(LUA_VERSION)
LUASRCDIR ?= $(LUATOP)/src LUASRCDIR ?= $(LUATOP)/src
LUAOBJFILES1 = $(TARGETPFX)lapi.o $(TARGETPFX)lauxlib.o \ LUAOBJFILES1 = $(TARGETPFX)lapi.o $(TARGETPFX)lauxlib.o \
+1 -1
View File
@@ -1147,7 +1147,7 @@ mswin_select_menu(winid wid, int how, MENU_ITEM_P **selected)
/* /*
-- Indicate to the window port that the inventory has been changed. -- Indicate to the window port that the inventory has been changed.
-- Merely calls display_inventory() for window-ports that leave the -- Merely calls repopulate_perminvent() for window-ports that leave the
window up, otherwise empty. window up, otherwise empty.
*/ */
void void
-8
View File
@@ -1,8 +0,0 @@
set -x
mkdir -p lib
cd lib
git clone --depth 1 https://github.com/wmcbrine/PDCurses.git pdcurses
#git clone --depth 1 https://github.com/universal-ctags/ctags.git ctags
curl -R -O http://www.lua.org/ftp/lua-5.4.6.tar.gz
tar zxf lua-5.4.6.tar.gz
cd ../
-49
View File
@@ -1,49 +0,0 @@
set -x
export VSVER=2017
export MSVER=14.16.27023
export SDKVER=10.0.17763.0
export FRAMEVER=4.0.30319
export NETFXVER=4.6.1
export WKITVER=10.0.17134.0
#export TOOLSVER=Enterprise
export TOOLSVER=BuildTools
export PATH=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/Common7/IDE/VC/VCPackages:$PATH
export PATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/10/bin/$WKITVER/x64:$PATH
export PATH=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/VC/Tools/MSVC/$MSVER/bin/HostX64/x64:$PATH
export PATH=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/VC/Tools/MSVC/$MSVER/bin/HostX64/x86:$PATH
export PATH=$PATH:/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/Common7/IDE/CommonExtensions/Microsoft/TestWindow
export PATH=$PATH:/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/MSBuild/Current/bin/Roslyn
export INCLUDE=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/2017/$TOOLSVER/VC/Tools/MSVC/$MSVER/include
export INCLUDE=$INCLUDE:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/Include/$WKITVER/ucrt
export INCLUDE=$INCLUDE:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/include/$WKITVER/ucrt
export INCLUDE=$INCLUDE:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/include/$WKITVER/shared
export INCLUDE=$INCLUDE:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/include/$WKITVER/um
export INCLUDE=$INCLUDE:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/include/$WKITVER/winrt
export INCLUDE=$INCLUDE:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/include/$WKITVER/cppwinrt
export LIB=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/VC/Tools/MSVC/$MSVER/ATLMFC/lib/x86
export LIB=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVER/VC/Tools/MSVC/$MSVER/lib/x86:$LIB
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/10/lib/$WKITVER/ucrt/x86:$LIB
export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/10/lib/$WKITVER/um/x86:$LIB
export LUA_VERSION=5.4.3
mkdir -p lib
cd lib
git clone --depth 1 https://github.com/wmcbrine/PDCurses.git pdcurses
#git clone --depth 1 https://github.com/universal-ctags/ctags.git ctags
curl -R -O http://www.lua.org/ftp/lua-$LUA_VERSION.tar.gz
tar zxf lua-$LUA_VERSION.tar.gz
#cd ctags
#nmake -f mk_mvc.mak
#cd ../../
cd ../
test -d "lib/lua-$LUA_VERSION/src" || echo "Lua-$LUA_VERSION fetch failed"
test -d "lib/pdcurses" || echo "pdcurses fetch failed"
test -d "lib/pdcurses" || exit 0
test -d "lib/lua-$LUA_VERSION/src" || exit 0
export ADD_CURSES=Y
export PDCURSES_TOP=../lib/pdcurses
export
cd src
cp ../sys/windows/Makefile.nmake ./Makefile
nmake install
cd ..
powershell -Command "Compress-Archive -U -Path binary/* -DestinationPath $TRAVIS_TAG.x86.zip"
+1 -1
View File
@@ -4850,7 +4850,7 @@ void NetHackQtBind::qt_update_inventory()
main->updateInventory(); main->updateInventory();
/* doesn't work yet /* doesn't work yet
if (program_state.something_worth_saving && iflags.perm_invent) if (program_state.something_worth_saving && iflags.perm_invent)
display_inventory(NULL, FALSE); repopulate_perminvent();
*/ */
} }
+1 -1
View File
@@ -786,7 +786,7 @@ gnome_select_menu(winid wid, int how, MENU_ITEM_P **selected)
/* /*
-- Indicate to the window port that the inventory has been changed. -- Indicate to the window port that the inventory has been changed.
-- Merely calls display_inventory() for window-ports that leave the -- Merely calls repopulate_perminvent() for window-ports that leave the
window up, otherwise empty. window up, otherwise empty.
*/ */
void void
+1
View File
@@ -16,6 +16,7 @@ nethack
tiles.bmp tiles.bmp
*.moc *.moc
*.lnk *.lnk
*.rsp
graphicschk graphicschk
nhdat nhdat
o o
+53 -408
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 allmain.c $NHDT-Date: 1744860497 2025/04/16 19:28:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.276 $ */ /* NetHack 3.7 allmain.c $NHDT-Date: 1771213100 2026/02/15 19:38:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.286 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -13,6 +13,7 @@
staticfn void moveloop_preamble(boolean); staticfn void moveloop_preamble(boolean);
staticfn void u_calc_moveamt(int); staticfn void u_calc_moveamt(int);
staticfn void maybe_generate_rnd_mon(void);
staticfn void maybe_do_tutorial(void); staticfn void maybe_do_tutorial(void);
#ifdef POSITIONBAR #ifdef POSITIONBAR
staticfn void do_positionbar(void); staticfn void do_positionbar(void);
@@ -20,10 +21,6 @@ staticfn void do_positionbar(void);
staticfn void regen_pw(int); staticfn void regen_pw(int);
staticfn void regen_hp(int); staticfn void regen_hp(int);
staticfn void interrupt_multi(const char *); staticfn void interrupt_multi(const char *);
staticfn void debug_fields(const char *);
#ifndef NODUMPENUMS
staticfn void dump_enums(void);
#endif
#ifdef CRASHREPORT #ifdef CRASHREPORT
#define USED_FOR_CRASHREPORT #define USED_FOR_CRASHREPORT
@@ -90,7 +87,7 @@ moveloop_preamble(boolean resuming)
fix_shop_damage(); fix_shop_damage();
} }
(void) encumber_msg(); /* in case they auto-picked up something */ encumber_msg(); /* in case they auto-picked up something */
if (gd.defer_see_monsters) { if (gd.defer_see_monsters) {
gd.defer_see_monsters = FALSE; gd.defer_see_monsters = FALSE;
see_monsters(); see_monsters();
@@ -161,6 +158,16 @@ u_calc_moveamt(int wtcap)
u.umovement = 0; u.umovement = 0;
} }
/* small chance of generating a new random monster */
staticfn void
maybe_generate_rnd_mon(void)
{
if (!rn2(u.uevent.udemigod ? 25
: (depth(&u.uz) > depth(&stronghold_level)) ? 50
: 70))
(void) makemon((struct permonst *) 0, 0, 0, NO_MM_FLAGS);
}
#if defined(MICRO) || defined(WIN32) #if defined(MICRO) || defined(WIN32)
static int mvl_abort_lev; static int mvl_abort_lev;
#endif #endif
@@ -180,6 +187,8 @@ moveloop_core(void)
#ifdef POSITIONBAR #ifdef POSITIONBAR
do_positionbar(); do_positionbar();
#endif #endif
if (iflags.pending_customizations)
maybe_shuffle_customizations();
dobjsfree(); dobjsfree();
@@ -197,9 +206,10 @@ moveloop_core(void)
u.umovement -= NORMAL_SPEED; u.umovement -= NORMAL_SPEED;
do { /* hero can't move this turn loop */ do { /* hero can't move this turn loop */
mvl_wtcap = encumber_msg(); encumber_msg();
svc.context.mon_moving = TRUE; svc.context.mon_moving = TRUE;
gu.uhp_at_start_of_monster_turn = u.uhp;
do { do {
monscanmove = movemon(); monscanmove = movemon();
if (u.umovement >= NORMAL_SPEED) if (u.umovement >= NORMAL_SPEED)
@@ -207,6 +217,10 @@ moveloop_core(void)
} while (monscanmove); } while (monscanmove);
svc.context.mon_moving = FALSE; svc.context.mon_moving = FALSE;
/* this needs to be after the monster movement loop in
case monster actions affected burden, e.g. rehumanize */
mvl_wtcap = near_capacity();
if (!monscanmove && u.umovement < NORMAL_SPEED) { if (!monscanmove && u.umovement < NORMAL_SPEED) {
/* both hero and monsters are out of steam this round */ /* both hero and monsters are out of steam this round */
struct monst *mtmp; struct monst *mtmp;
@@ -224,11 +238,7 @@ moveloop_core(void)
/* occasionally add another monster; since this takes /* occasionally add another monster; since this takes
place after movement has been allotted, the new place after movement has been allotted, the new
monster effectively loses its first turn */ monster effectively loses its first turn */
if (!rn2(u.uevent.udemigod ? 25 maybe_generate_rnd_mon();
: (depth(&u.uz) > depth(&stronghold_level)) ? 50
: 70))
(void) makemon((struct permonst *) 0, 0, 0,
NO_MM_FLAGS);
u_calc_moveamt(mvl_wtcap); u_calc_moveamt(mvl_wtcap);
settrack(); settrack();
@@ -268,6 +278,8 @@ moveloop_core(void)
if (u.ublesscnt) if (u.ublesscnt)
u.ublesscnt--; u.ublesscnt--;
gs.saving_grace_turn = FALSE;
/* One possible result of prayer is healing. Whether or /* One possible result of prayer is healing. Whether or
* not you get healed depends on your current hit points. * not you get healed depends on your current hit points.
* If you are allowed to regenerate during the prayer, * If you are allowed to regenerate during the prayer,
@@ -392,7 +404,7 @@ moveloop_core(void)
inventory may have changed in, e.g., nh_timeout(); we do inventory may have changed in, e.g., nh_timeout(); we do
need two checks here so that the player gets feedback need two checks here so that the player gets feedback
immediately if their own action encumbered them */ immediately if their own action encumbered them */
(void) encumber_msg(); encumber_msg();
#ifdef STATUS_HILITES #ifdef STATUS_HILITES
if (iflags.hilite_delta) if (iflags.hilite_delta)
@@ -419,6 +431,8 @@ moveloop_core(void)
else if (!u.umoved) else if (!u.umoved)
(void) pooleffects(FALSE); (void) pooleffects(FALSE);
gs.saving_grace_turn = FALSE;
/* vision while buried or underwater is updated here */ /* vision while buried or underwater is updated here */
if (Underwater) if (Underwater)
under_water(0); under_water(0);
@@ -437,6 +451,8 @@ moveloop_core(void)
/* the Amulet of Yendor gives a wish when initially picked up */ /* the Amulet of Yendor gives a wish when initially picked up */
if (u.uhave.amulet && !u.uevent.amulet_wish) { if (u.uhave.amulet && !u.uevent.amulet_wish) {
u.uevent.amulet_wish = 1; u.uevent.amulet_wish = 1;
display_nhwindow(WIN_MESSAGE, TRUE);
urgent_pline("The Amulet is bestowing a wish upon you!");
makewish(); makewish();
} }
@@ -500,11 +516,6 @@ moveloop_core(void)
return; return;
} }
#ifdef CLIPPING
/* just before rhack */
cliparound(u.ux, u.uy);
#endif
u.umoved = FALSE; u.umoved = FALSE;
if (gm.multi > 0) { if (gm.multi > 0) {
@@ -536,6 +547,11 @@ moveloop_core(void)
if (gv.vision_full_recalc) if (gv.vision_full_recalc)
vision_recalc(0); /* vision! */ vision_recalc(0); /* vision! */
#ifdef CLIPPING
/* after rhack() and vision_recalc() so that the map is redrawn
once with correct vision data, not twice (overshoot+correct) */
cliparound(u.ux, u.uy);
#endif
/* when running in non-tport mode, this gets done through domove() */ /* when running in non-tport mode, this gets done through domove() */
if ((!svc.context.run || flags.runmode == RUN_TPORT) if ((!svc.context.run || flags.runmode == RUN_TPORT)
&& (gm.multi && (!svc.context.travel ? !(gm.multi % 7) && (gm.multi && (!svc.context.travel ? !(gm.multi % 7)
@@ -597,6 +613,9 @@ regen_pw(int wtcap)
/ 6)))) || Energy_regeneration)) { / 6)))) || Energy_regeneration)) {
int upper = (int) (ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1; int upper = (int) (ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1;
if (EMagical_breathing)
upper += 2;
u.uen += rn1(upper, 1); u.uen += rn1(upper, 1);
if (u.uen > u.uenmax) if (u.uen > u.uenmax)
u.uen = u.uenmax; u.uen = u.uenmax;
@@ -748,7 +767,7 @@ init_sound_disp_gamewindows(void)
if (iflags.perm_invent_pending) if (iflags.perm_invent_pending)
check_perm_invent_again(); check_perm_invent_again();
#endif #endif
} }
void void
newgame(void) newgame(void)
@@ -778,7 +797,7 @@ newgame(void)
* in hero's initial inventory */ * in hero's initial inventory */
init_artifacts(); /* before u_init() in case $WIZKIT specifies init_artifacts(); /* before u_init() in case $WIZKIT specifies
* any artifacts */ * any artifacts */
u_init(); u_init_misc();
l_nhcore_init(); /* create a Lua state that lasts until end of game */ l_nhcore_init(); /* create a Lua state that lasts until end of game */
reset_glyphmap(gm_newgame); reset_glyphmap(gm_newgame);
@@ -793,18 +812,29 @@ newgame(void)
mklev(); mklev();
u_on_upstairs(); u_on_upstairs();
if (wizard)
obj_delivery(FALSE); /* finish wizkit */
vision_reset(); /* set up internals for level (after mklev) */ vision_reset(); /* set up internals for level (after mklev) */
check_special_room(FALSE); check_special_room(FALSE);
if (MON_AT(u.ux, u.uy)) if (MON_AT(u.ux, u.uy))
mnexto(m_at(u.ux, u.uy), RLOC_NOMSG); mnexto(m_at(u.ux, u.uy), RLOC_NOMSG);
(void) makedog(); (void) makedog();
u_init_inventory_attrs();
docrt(); docrt();
flush_screen(1);
bot();
while (u.uroleplay.reroll && reroll_menu()) {
u_init_inventory_attrs();
bot();
}
u_init_skills_discoveries();
if (wizard) {
read_wizkit();
obj_delivery(FALSE); /* finish wizkit */
}
if (flags.legacy) { if (flags.legacy) {
flush_screen(1);
com_pager(u.uroleplay.pauper ? "pauper_legacy" : "legacy"); com_pager(u.uroleplay.pauper ? "pauper_legacy" : "legacy");
} }
@@ -939,218 +969,6 @@ interrupt_multi(const char *msg)
} }
} }
/*
* Argument processing helpers - for xxmain() to share
* and call.
*
* These should return TRUE if the argument matched,
* whether the processing of the argument was
* successful or not.
*
* Most of these do their thing, then after returning
* to xxmain(), the code exits without starting a game.
*
*/
static const struct early_opt earlyopts[] = {
{ ARG_DEBUG, "debug", 5, TRUE },
{ ARG_VERSION, "version", 4, TRUE },
{ ARG_SHOWPATHS, "showpaths", 8, FALSE },
#ifndef NODUMPENUMS
{ ARG_DUMPENUMS, "dumpenums", 9, FALSE },
#endif
{ ARG_DUMPGLYPHIDS, "dumpglyphids", 12, FALSE },
{ ARG_DUMPMONGEN, "dumpmongen", 10, FALSE },
{ ARG_DUMPWEIGHTS, "dumpweights", 11, FALSE },
#ifdef WIN32
{ ARG_WINDOWS, "windows", 4, TRUE },
#endif
#if defined(CRASHREPORT)
{ ARG_BIDSHOW, "bidshow", 7, FALSE },
#endif
};
#ifdef WIN32
extern int windows_early_options(const char *);
#endif
/*
* Returns:
* 0 = no match
* 1 = found and skip past this argument
* 2 = found and trigger immediate exit
*/
int
argcheck(int argc, char *argv[], enum earlyarg e_arg)
{
int i, idx;
boolean match = FALSE;
char *userea = (char *) 0;
const char *dashdash = "";
for (idx = 0; idx < SIZE(earlyopts); idx++) {
if (earlyopts[idx].e == e_arg){
break;
}
}
if (idx >= SIZE(earlyopts) || argc < 1)
return 0;
for (i = 0; i < argc; ++i) {
if (argv[i][0] != '-')
continue;
if (argv[i][1] == '-') {
userea = &argv[i][2];
dashdash = "-";
} else {
userea = &argv[i][1];
}
match = match_optname(userea, earlyopts[idx].name,
earlyopts[idx].minlength,
earlyopts[idx].valallowed);
if (match)
break;
}
if (match) {
const char *extended_opt = strchr(userea, ':');
if (!extended_opt)
extended_opt = strchr(userea, '=');
switch(e_arg) {
case ARG_DEBUG:
if (extended_opt) {
extended_opt++;
debug_fields(extended_opt);
}
return 1;
case ARG_VERSION: {
boolean insert_into_pastebuf = FALSE;
if (extended_opt) {
extended_opt++;
/* Deprecated in favor of "copy" - remove no later
than next major version */
if (match_optname(extended_opt, "paste", 5, FALSE)) {
insert_into_pastebuf = TRUE;
} else if (match_optname(extended_opt, "copy", 4, FALSE)) {
insert_into_pastebuf = TRUE;
} else if (match_optname(extended_opt, "dump", 4, FALSE)) {
/* version number plus enabled features and sanity
values that the program compares against the same
thing recorded in save and bones files to check
whether they're being used compatibly */
dump_version_info();
return 2; /* done */
} else if (!match_optname(extended_opt, "show", 4, FALSE)) {
raw_printf("-%sversion can only be extended with"
" -%sversion:copy or :dump or :show.\n",
dashdash, dashdash);
/* exit after we've reported bad command line argument */
return 2;
}
}
early_version_info(insert_into_pastebuf);
return 2;
}
case ARG_SHOWPATHS:
return 2;
#ifndef NODUMPENUMS
case ARG_DUMPENUMS:
dump_enums();
return 2;
#endif
case ARG_DUMPGLYPHIDS:
dump_glyphids();
return 2;
case ARG_DUMPMONGEN:
dump_mongen();
return 2;
case ARG_DUMPWEIGHTS:
dump_weights();
return 2;
#ifdef CRASHREPORT
case ARG_BIDSHOW:
crashreport_bidshow();
return 2;
#endif
#ifdef WIN32
case ARG_WINDOWS:
if (extended_opt) {
extended_opt++;
return windows_early_options(extended_opt);
}
FALLTHROUGH;
/*FALLTHRU*/
#endif
default:
break;
}
};
return 0;
}
/*
* These are internal controls to aid developers with
* testing and debugging particular aspects of the code.
* They are not player options and the only place they
* are documented is right here. No gameplay is altered.
*
* test - test whether this parser is working
* ttystatus - TTY:
* immediateflips - WIN32: turn off display performance
* optimization so that display output
* can be debugged without buffering.
* fuzzer - enable fuzzer without debugger intervention.
*/
staticfn void
debug_fields(const char *opts)
{
char *op;
boolean negated = FALSE;
while ((op = strchr(opts, ',')) != 0) {
*op++ = 0;
/* recurse */
debug_fields(op);
}
if (strlen(opts) > BUFSZ / 2)
return;
/* strip leading and trailing white space */
while (isspace((uchar) *opts))
opts++;
op = eos((char *) opts);
while (--op >= opts && isspace((uchar) *op))
*op = '\0';
if (!*opts) {
/* empty */
return;
}
while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
if (*opts == '!')
opts++;
else
opts += 2;
negated = !negated;
}
if (match_optname(opts, "test", 4, FALSE))
iflags.debug.test = negated ? FALSE : TRUE;
#ifdef TTY_GRAPHICS
if (match_optname(opts, "ttystatus", 9, FALSE))
iflags.debug.ttystatus = negated ? FALSE : TRUE;
#endif
#ifdef WIN32
if (match_optname(opts, "immediateflips", 14, FALSE))
iflags.debug.immediateflips = negated ? FALSE : TRUE;
#endif
if (match_optname(opts, "fuzzer", 4, FALSE))
iflags.fuzzerpending = TRUE;
return;
}
/* convert from time_t to number of seconds */ /* convert from time_t to number of seconds */
long long
timet_to_seconds(time_t ttim) timet_to_seconds(time_t ttim)
@@ -1169,177 +987,4 @@ timet_delta(time_t etim, time_t stim) /* end and start times */
return (long) difftime(etim, stim); return (long) difftime(etim, stim);
} }
#if !defined(NODUMPENUMS)
/* monsdump[] and objdump[] are also used in utf8map.c */
#define DUMP_ENUMS
#define UNPREFIXED_COUNT (5)
struct enum_dump monsdump[] = {
#include "monsters.h"
{ NUMMONS, "NUMMONS" },
{ NON_PM, "NON_PM" },
{ LOW_PM, "LOW_PM" },
{ HIGH_PM, "HIGH_PM" },
{ SPECIAL_PM, "SPECIAL_PM" }
};
struct enum_dump objdump[] = {
#include "objects.h"
{ NUM_OBJECTS, "NUM_OBJECTS" },
};
#define DUMP_ENUMS_PCHAR
static struct enum_dump defsym_cmap_dump[] = {
#include "defsym.h"
{ MAXPCHARS, "MAXPCHARS" },
};
#undef DUMP_ENUMS_PCHAR
#define DUMP_ENUMS_MONSYMS
static struct enum_dump defsym_mon_syms_dump[] = {
#include "defsym.h"
{ MAXMCLASSES, "MAXMCLASSES" },
};
#undef DUMP_ENUMS_MONSYMS
#define DUMP_ENUMS_MONSYMS_DEFCHAR
static struct enum_dump defsym_mon_defchars_dump[] = {
#include "defsym.h"
};
#undef DUMP_ENUMS_MONSYMS_DEFCHAR
#define DUMP_ENUMS_OBJCLASS_DEFCHARS
static struct enum_dump objclass_defchars_dump[] = {
#include "defsym.h"
};
#undef DUMP_ENUMS_OBJCLASS_DEFCHARS
#define DUMP_ENUMS_OBJCLASS_CLASSES
static struct enum_dump objclass_classes_dump[] = {
#include "defsym.h"
{ MAXOCLASSES, "MAXOCLASSES" },
};
#undef DUMP_ENUMS_OBJCLASS_CLASSES
#define DUMP_ENUMS_OBJCLASS_SYMS
static struct enum_dump objclass_syms_dump[] = {
#include "defsym.h"
};
#undef DUMP_ENUMS_OBJCLASS_SYMS
#define DUMP_ARTI_ENUM
static struct enum_dump arti_enum_dump[] = {
#include "artilist.h"
{ AFTER_LAST_ARTIFACT, "AFTER_LAST_ARTIFACT" }
};
#undef DUMP_ARTI_ENUM
#undef DUMP_ENUMS
#ifndef NODUMPENUMS
staticfn void
dump_enums(void)
{
enum enum_dumps {
monsters_enum,
objects_enum,
objects_misc_enum,
defsym_cmap_enum,
defsym_mon_syms_enum,
defsym_mon_defchars_enum,
objclass_defchars_enum,
objclass_classes_enum,
objclass_syms_enum,
arti_enum,
NUM_ENUM_DUMPS
};
#define dump_om(om) { om, #om }
static const struct enum_dump omdump[] = {
dump_om(LAST_GENERIC),
dump_om(OBJCLASS_HACK),
dump_om(FIRST_OBJECT),
dump_om(FIRST_AMULET),
dump_om(LAST_AMULET),
dump_om(FIRST_SPELL),
dump_om(LAST_SPELL),
dump_om(MAXSPELL),
dump_om(FIRST_REAL_GEM),
dump_om(LAST_REAL_GEM),
dump_om(FIRST_GLASS_GEM),
dump_om(LAST_GLASS_GEM),
dump_om(NUM_REAL_GEMS),
dump_om(NUM_GLASS_GEMS),
dump_om(MAX_GLYPH),
};
#undef dump_om
static const struct enum_dump *const ed[NUM_ENUM_DUMPS] = {
monsdump, objdump, omdump,
defsym_cmap_dump, defsym_mon_syms_dump,
defsym_mon_defchars_dump,
objclass_defchars_dump,
objclass_classes_dump,
objclass_syms_dump,
arti_enum_dump,
};
static const struct de_params {
const char *const title;
const char *const pfx;
int unprefixed_count;
int dumpflgs; /* 0 = dump numerically only, 1 = add 'char' comment */
int szd;
} edmp[NUM_ENUM_DUMPS] = {
{ "monnums", "PM_", UNPREFIXED_COUNT, 0, SIZE(monsdump) },
{ "objects_nums", "", 1, 0, SIZE(objdump) },
{ "misc_object_nums", "", 1, 0, SIZE(omdump) },
{ "cmap_symbols", "", 1, 0, SIZE(defsym_cmap_dump) },
{ "mon_syms", "", 1, 0, SIZE(defsym_mon_syms_dump) },
{ "mon_defchars", "", 1, 1, SIZE(defsym_mon_defchars_dump) },
{ "objclass_defchars", "", 1, 1, SIZE(objclass_defchars_dump) },
{ "objclass_classes", "", 1, 0, SIZE(objclass_classes_dump) },
{ "objclass_syms", "", 1, 0, SIZE(objclass_syms_dump) },
{ "artifacts_nums", "", 1, 0, SIZE(arti_enum_dump) },
};
const char *nmprefix;
int i, j, nmwidth;
char comment[BUFSZ];
for (i = 0; i < NUM_ENUM_DUMPS; ++ i) {
raw_printf("enum %s = {", edmp[i].title);
for (j = 0; j < edmp[i].szd; ++j) {
nmprefix = (j >= edmp[i].szd - edmp[i].unprefixed_count)
? "" : edmp[i].pfx; /* "" or "PM_" */
nmwidth = 27 - (int) strlen(nmprefix); /* 27 or 24 */
if (edmp[i].dumpflgs > 0) {
Snprintf(comment, sizeof comment,
" /* '%c' */",
(ed[i][j].val >= 32 && ed[i][j].val <= 126)
? ed[i][j].val : ' ');
} else {
comment[0] = '\0';
}
raw_printf(" %s%*s = %3d,%s",
nmprefix, -nmwidth,
ed[i][j].nm, ed[i][j].val,
comment);
}
raw_print("};");
raw_print("");
}
raw_print("");
}
#undef UNPREFIXED_COUNT
#endif /* NODUMPENUMS */
void
dump_glyphids(void)
{
dump_all_glyphids(stdout);
}
#endif /* !NODUMPENUMS */
/*allmain.c*/ /*allmain.c*/
+16 -10
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 apply.c $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.472 $ */ /* NetHack 3.7 apply.c $NHDT-Date: 1769342601 2026/01/25 04:03:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.475 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -52,7 +52,7 @@ staticfn boolean check_jump(genericptr_t, coordxy, coordxy);
staticfn boolean is_valid_jump_pos(coordxy, coordxy, int, boolean); staticfn boolean is_valid_jump_pos(coordxy, coordxy, int, boolean);
staticfn boolean get_valid_jump_position(coordxy, coordxy); staticfn boolean get_valid_jump_position(coordxy, coordxy);
staticfn boolean get_valid_polearm_position(coordxy, coordxy); staticfn boolean get_valid_polearm_position(coordxy, coordxy);
staticfn boolean find_poleable_mon(coord *, int, int); staticfn boolean find_poleable_mon(coord *);
static const char static const char
no_elbow_room[] = "don't have enough elbow-room to maneuver."; no_elbow_room[] = "don't have enough elbow-room to maneuver.";
@@ -500,7 +500,7 @@ use_magic_whistle(struct obj *obj)
You("produce a %shigh-%s.", Underwater ? "very " : "", You("produce a %shigh-%s.", Underwater ? "very " : "",
Deaf ? "frequency vibration" : "pitched humming noise"); Deaf ? "frequency vibration" : "pitched humming noise");
wake_nearby(TRUE); wake_nearby(TRUE);
if (!rn2(2)) if (!rn2(2) && !noteleport_level(&gy.youmonst))
tele_to_rnd_pet(); tele_to_rnd_pet();
} else { } else {
/* it's magic! it works underwater too (at a higher pitch) */ /* it's magic! it works underwater too (at a higher pitch) */
@@ -526,6 +526,10 @@ magic_whistled(struct obj *obj)
already_discovered = objects[obj->otyp].oc_name_known != 0; already_discovered = objects[obj->otyp].oc_name_known != 0;
int omx, omy, shift = 0, appear = 0, disappear = 0, trapped = 0; int omx, omy, shift = 0, appear = 0, disappear = 0, trapped = 0;
/* stasis prevents magic-whistling */
if (svl.level.flags.stasis_until >= svm.moves)
return;
/* need to copy (up to 3) names as they're collected rather than just /* need to copy (up to 3) names as they're collected rather than just
save pointers to them, otherwise churning through every mbuf[] might save pointers to them, otherwise churning through every mbuf[] might
clobber the ones we care about */ clobber the ones we care about */
@@ -2583,6 +2587,8 @@ grease_ok(struct obj *obj)
if (!obj) if (!obj)
return GETOBJ_SUGGEST; return GETOBJ_SUGGEST;
/* note: if changing the list of ungreasable objects, also change
special_throne_effect in sit.c */
if (obj->oclass == COIN_CLASS) if (obj->oclass == COIN_CLASS)
return GETOBJ_EXCLUDE; return GETOBJ_EXCLUDE;
@@ -2683,7 +2689,7 @@ use_stone(struct obj *tstone)
/* in case it was acquired while blinded */ /* in case it was acquired while blinded */
if (!Blind) if (!Blind)
tstone->dknown = 1; observe_object(tstone);
known = (tstone->otyp == TOUCHSTONE && tstone->dknown known = (tstone->otyp == TOUCHSTONE && tstone->dknown
&& objects[TOUCHSTONE].oc_name_known); && objects[TOUCHSTONE].oc_name_known);
Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan)); Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan));
@@ -3274,7 +3280,7 @@ static const char
/* find pos of monster in range, if only one monster */ /* find pos of monster in range, if only one monster */
staticfn boolean staticfn boolean
find_poleable_mon(coord *pos, int min_range, int max_range) find_poleable_mon(coord *pos)
{ {
struct monst *mtmp; struct monst *mtmp;
coord mpos = { 0, 0 }; /* no candidate location yet */ coord mpos = { 0, 0 }; /* no candidate location yet */
@@ -3283,13 +3289,12 @@ find_poleable_mon(coord *pos, int min_range, int max_range)
int glyph; int glyph;
impaired = (Confusion || Stunned || Hallucination); impaired = (Confusion || Stunned || Hallucination);
rt = isqrt(max_range); rt = isqrt(gp.polearm_range_max);
lo_x = max(u.ux - rt, 1), hi_x = min(u.ux + rt, COLNO - 1); lo_x = max(u.ux - rt, 1), hi_x = min(u.ux + rt, COLNO - 1);
lo_y = max(u.uy - rt, 0), hi_y = min(u.uy + rt, ROWNO - 1); lo_y = max(u.uy - rt, 0), hi_y = min(u.uy + rt, ROWNO - 1);
for (x = lo_x; x <= hi_x; ++x) { for (x = lo_x; x <= hi_x; ++x) {
for (y = lo_y; y <= hi_y; ++y) { for (y = lo_y; y <= hi_y; ++y) {
if (distu(x, y) < min_range || distu(x, y) > max_range if (!get_valid_polearm_position(x, y))
|| !isok(x, y) || !cansee(x, y))
continue; continue;
glyph = glyph_at(x, y); glyph = glyph_at(x, y);
if (!impaired if (!impaired
@@ -3395,7 +3400,7 @@ could_pole_mon(void)
cc.x = u.ux; cc.x = u.ux;
cc.y = u.uy; cc.y = u.uy;
if (!find_poleable_mon(&cc, min_range, max_range)) { if (!find_poleable_mon(&cc)) {
if (hitm && !DEADMONSTER(hitm) && sensemon(hitm) if (hitm && !DEADMONSTER(hitm) && sensemon(hitm)
&& mdistu(hitm) <= max_range && mdistu(hitm) >= min_range) && mdistu(hitm) <= max_range && mdistu(hitm) >= min_range)
return TRUE; return TRUE;
@@ -3448,7 +3453,7 @@ use_pole(struct obj *obj, boolean autohit)
pline(where_to_hit); pline(where_to_hit);
cc.x = u.ux; cc.x = u.ux;
cc.y = u.uy; cc.y = u.uy;
if (!find_poleable_mon(&cc, min_range, max_range) && hitm if (!find_poleable_mon(&cc) && hitm
&& !DEADMONSTER(hitm) && sensemon(hitm) && !DEADMONSTER(hitm) && sensemon(hitm)
&& mdistu(hitm) <= max_range && mdistu(hitm) >= min_range) { && mdistu(hitm) <= max_range && mdistu(hitm) >= min_range) {
cc.x = hitm->mx; cc.x = hitm->mx;
@@ -3982,6 +3987,7 @@ do_break_wand(struct obj *obj)
case WAN_PROBING: case WAN_PROBING:
case WAN_ENLIGHTENMENT: case WAN_ENLIGHTENMENT:
case WAN_SECRET_DOOR_DETECTION: case WAN_SECRET_DOOR_DETECTION:
case WAN_STASIS:
pline(nothing_else_happens); pline(nothing_else_happens);
discard_broken_wand(); discard_broken_wand();
return ECMD_TIME; return ECMD_TIME;
+50 -13
View File
@@ -40,6 +40,8 @@ staticfn int invoke_banish(struct obj *) NONNULLARG1;
staticfn int invoke_fling_poison(struct obj *) NONNULLARG1; staticfn int invoke_fling_poison(struct obj *) NONNULLARG1;
staticfn int invoke_storm_spell(struct obj *) NONNULLARG1; staticfn int invoke_storm_spell(struct obj *) NONNULLARG1;
staticfn int invoke_blinding_ray(struct obj *) NONNULLARG1; staticfn int invoke_blinding_ray(struct obj *) NONNULLARG1;
staticfn int arti_invoke_cost_pw(struct obj *) NONNULLARG1;
staticfn boolean arti_invoke_cost(struct obj *) NONNULLARG1;
staticfn int arti_invoke(struct obj *); staticfn int arti_invoke(struct obj *);
staticfn boolean Mb_hit(struct monst * magr, struct monst *mdef, staticfn boolean Mb_hit(struct monst * magr, struct monst *mdef,
struct obj *, int *, int, boolean, char *); struct obj *, int *, int, boolean, char *);
@@ -1570,7 +1572,7 @@ artifact_hit(
} }
*dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
pline("%s cuts %s in half!", wepdesc, mon_nam(mdef)); pline("%s cuts %s in half!", wepdesc, mon_nam(mdef));
otmp->dknown = TRUE; observe_object(otmp);
return TRUE; return TRUE;
} else { } else {
if (bigmonst(gy.youmonst.data)) { if (bigmonst(gy.youmonst.data)) {
@@ -1587,7 +1589,7 @@ artifact_hit(
*/ */
*dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER; *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
pline("%s cuts you in half!", wepdesc); pline("%s cuts you in half!", wepdesc);
otmp->dknown = TRUE; observe_object(otmp);
return TRUE; return TRUE;
} }
} else if (is_art(otmp, ART_VORPAL_BLADE) } else if (is_art(otmp, ART_VORPAL_BLADE)
@@ -1617,7 +1619,7 @@ artifact_hit(
mon_nam(mdef)); mon_nam(mdef));
if (Hallucination && !flags.female) if (Hallucination && !flags.female)
pline("Good job Henry, but that wasn't Anne."); pline("Good job Henry, but that wasn't Anne.");
otmp->dknown = TRUE; observe_object(otmp);
return TRUE; return TRUE;
} else { } else {
if (!has_head(gy.youmonst.data)) { if (!has_head(gy.youmonst.data)) {
@@ -1634,7 +1636,7 @@ artifact_hit(
} }
*dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER; *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
pline(ROLL_FROM(behead_msg), wepdesc, "you"); pline(ROLL_FROM(behead_msg), wepdesc, "you");
otmp->dknown = TRUE; observe_object(otmp);
/* Should amulets fall off? */ /* Should amulets fall off? */
return TRUE; return TRUE;
} }
@@ -2083,6 +2085,48 @@ invoke_blinding_ray(struct obj *obj)
return ECMD_TIME; return ECMD_TIME;
} }
/* return the amount of Pw invoking an object costs.
return a negative value, if obj invoking cannot be paid with Pw */
staticfn int
arti_invoke_cost_pw(struct obj *obj)
{
const struct artifact *oart = get_artifact(obj);
if (oart->inv_prop == FLING_POISON
|| oart->inv_prop == BLINDING_RAY) {
/* pretend it's a level 5 spell */
return SPELL_LEV_PW(5);
}
return -1;
}
/* return TRUE if artifact object's invoke cost can be paid (and pay it) */
staticfn boolean
arti_invoke_cost(struct obj *obj)
{
if (obj->age > svm.moves) {
int pw_cost = arti_invoke_cost_pw(obj);
if (pw_cost < 0 || u.uen < pw_cost) {
/* the artifact is tired :-) */
You_feel("that %s %s ignoring you.", the(xname(obj)),
otense(obj, "are"));
/* and just got more so; patience is essential... */
obj->age += (long) d(3, 10);
return FALSE;
} else {
/* you pay invoke cost with your own magic */
You_feel("drained...");
u.uen -= pw_cost;
disp.botl = TRUE;
}
} else {
obj->age = svm.moves + rnz(100);
}
return TRUE;
}
staticfn int staticfn int
arti_invoke(struct obj *obj) arti_invoke(struct obj *obj)
{ {
@@ -2102,17 +2146,10 @@ arti_invoke(struct obj *obj)
return ECMD_TIME; return ECMD_TIME;
} }
/* It's a special power, not "just" a property */
if (oart->inv_prop > LAST_PROP) { if (oart->inv_prop > LAST_PROP) {
/* It's a special power, not "just" a property */ if (!arti_invoke_cost(obj))
if (obj->age > svm.moves) {
/* the artifact is tired :-) */
You_feel("that %s %s ignoring you.", the(xname(obj)),
otense(obj, "are"));
/* and just got more so; patience is essential... */
obj->age += (long) d(3, 10);
return ECMD_TIME; return ECMD_TIME;
}
obj->age = svm.moves + rnz(100);
switch (oart->inv_prop) { switch (oart->inv_prop) {
case TAMING: res = invoke_taming(obj); break; case TAMING: res = invoke_taming(obj); break;
+8 -5
View File
@@ -187,11 +187,14 @@ adjattrib(
return FALSE; return FALSE;
} }
/* Any successful change also resets abuse / exercise level */
AEXE(ndx) = 0;
disp.botl = TRUE; disp.botl = TRUE;
if (msgflg <= 0) if (msgflg <= 0)
You_feel("%s%s!", (incr > 1 || incr < -1) ? "very " : "", attrstr); You_feel("%s%s!", (incr > 1 || incr < -1) ? "very " : "", attrstr);
if (program_state.in_moveloop && (ndx == A_STR || ndx == A_CON)) if (program_state.in_moveloop && (ndx == A_STR || ndx == A_CON))
(void) encumber_msg(); encumber_msg();
return TRUE; return TRUE;
} }
@@ -401,7 +404,7 @@ poisoned(
/* "Poisoned by a poisoned ___" is redundant */ /* "Poisoned by a poisoned ___" is redundant */
done(strstri(pkiller, "poison") ? DIED : POISONING); done(strstri(pkiller, "poison") ? DIED : POISONING);
} }
(void) encumber_msg(); encumber_msg();
} }
void void
@@ -477,7 +480,7 @@ restore_attrib(void)
} }
} }
if (disp.botl) if (disp.botl)
(void) encumber_msg(); encumber_msg();
} }
#define AVAL 50 /* tune value for exercise gains */ #define AVAL 50 /* tune value for exercise gains */
@@ -511,7 +514,7 @@ exercise(int i, boolean inc_or_dec)
(inc_or_dec) ? "inc" : "dec", AEXE(i)); (inc_or_dec) ? "inc" : "dec", AEXE(i));
} }
if (svm.moves > 0 && (i == A_STR || i == A_CON)) if (svm.moves > 0 && (i == A_STR || i == A_CON))
(void) encumber_msg(); encumber_msg();
} }
staticfn void staticfn void
@@ -753,7 +756,7 @@ redist_attr(void)
if (ABASE(i) < ATTRMIN(i)) if (ABASE(i) < ATTRMIN(i))
ABASE(i) = ATTRMIN(i); ABASE(i) = ATTRMIN(i);
} }
/* (void) encumber_msg(); -- caller needs to do this */ /* encumber_msg(); -- caller needs to do this */
} }
/* apply minor variation to attributes */ /* apply minor variation to attributes */
+1 -1
View File
@@ -34,7 +34,7 @@ ballrelease(boolean showmsg)
/* [this used to test 'if (uwep != uball)' but that always passes /* [this used to test 'if (uwep != uball)' but that always passes
after the setuwep() above] */ after the setuwep() above] */
freeinv(uball); /* remove from inventory but don't place on floor */ freeinv(uball); /* remove from inventory but don't place on floor */
(void) encumber_msg(); encumber_msg();
} }
} }
+14 -11
View File
@@ -1,12 +1,9 @@
/* NetHack 3.7 botl.c $NHDT-Date: 1742207239 2025/03/17 02:27:19 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.274 $ */ /* NetHack 3.7 botl.c $NHDT-Date: 1769839231 2026/01/30 22:00:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.277 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */ /*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
#include "hack.h" #include "hack.h"
#ifndef LONG_MAX
#include <limits.h>
#endif
extern const char *const hu_stat[]; /* defined in eat.c */ extern const char *const hu_stat[]; /* defined in eat.c */
@@ -19,9 +16,8 @@ const char *const enc_stat[] = {
staticfn const char *rank(void); staticfn const char *rank(void);
staticfn void bot_via_windowport(void); staticfn void bot_via_windowport(void);
staticfn void stat_update_time(void); staticfn void stat_update_time(void);
staticfn char *get_strength_str(void);
staticfn char * char *
get_strength_str(void) get_strength_str(void)
{ {
static char buf[32]; static char buf[32];
@@ -61,7 +57,7 @@ do_statusline1(void)
Strcpy(newbot1, svp.plname); Strcpy(newbot1, svp.plname);
if ('a' <= newbot1[0] && newbot1[0] <= 'z') if ('a' <= newbot1[0] && newbot1[0] <= 'z')
newbot1[0] += 'A' - 'a'; newbot1[0] += 'A' - 'a';
newbot1[10] = 0; newbot1[BOTL_NSIZ] = 0;
Sprintf(nb = eos(newbot1), " the "); Sprintf(nb = eos(newbot1), " the ");
if (Upolyd) { if (Upolyd) {
@@ -773,12 +769,12 @@ bot_via_windowport(void)
nb[0] = highc(nb[0]); nb[0] = highc(nb[0]);
titl = !Upolyd ? rank() : pmname(&mons[u.umonnum], Ugender); titl = !Upolyd ? rank() : pmname(&mons[u.umonnum], Ugender);
i = (int) (strlen(buf) + sizeof " the " + strlen(titl) - sizeof ""); i = (int) (strlen(buf) + sizeof " the " + strlen(titl) - sizeof "");
/* if "Name the Rank/monster" is too long, we truncate the name /* if "Name the Rank/monster" is too long, we truncate the name but
but always keep at least 10 characters of it; when hitpointbar is always keep at least BOTL_NSIZ characters of it; when hitpointbar is
enabled, anything beyond 30 (long monster name) will be truncated */ enabled, anything beyond 30 (long monster name) will be truncated */
if (i > 30) { if (i > 30) {
i = 30 - (int) (sizeof " the " + strlen(titl) - sizeof ""); i = 30 - (int) (sizeof " the " + strlen(titl) - sizeof "");
nb[max(i, 10)] = '\0'; nb[max(i, BOTL_NSIZ)] = '\0';
} }
Strcpy(nb = eos(nb), " the "); Strcpy(nb = eos(nb), " the ");
Strcpy(nb = eos(nb), titl); Strcpy(nb = eos(nb), titl);
@@ -3641,6 +3637,7 @@ status_hilite_menu_add(int origfld)
unsigned long cond = 0UL; unsigned long cond = 0UL;
char colorqry[BUFSZ]; char colorqry[BUFSZ];
char attrqry[BUFSZ]; char attrqry[BUFSZ];
int retry = 0;
choose_field: choose_field:
fld = origfld; fld = origfld;
@@ -3676,6 +3673,10 @@ status_hilite_menu_add(int origfld)
hilite.behavior = behavior; hilite.behavior = behavior;
choose_value: choose_value:
if (retry++ > 5) {
pline("That's enough tries.");
return FALSE;
}
if (behavior == BL_TH_VAL_PERCENTAGE if (behavior == BL_TH_VAL_PERCENTAGE
|| behavior == BL_TH_VAL_ABSOLUTE) { || behavior == BL_TH_VAL_ABSOLUTE) {
char inbuf[BUFSZ], buf[BUFSZ]; char inbuf[BUFSZ], buf[BUFSZ];
@@ -4302,7 +4303,9 @@ status_hilite_menu(void)
countall = status_hilite_linestr_countfield(BL_FLUSH); countall = status_hilite_linestr_countfield(BL_FLUSH);
status_hilite_linestr_done(); status_hilite_linestr_done();
if (redo) /* fuzzer is unlikely to pick something useful within nested menus;
limit it to one try */
if (redo && !iflags.debug_fuzzer)
goto shlmenu_redo; goto shlmenu_redo;
/* hilite_delta=='statushilites' does double duty: it is the /* hilite_delta=='statushilites' does double duty: it is the
+160 -9
View File
@@ -34,7 +34,7 @@ staticfn void free_config_sections(void);
staticfn char *is_config_section(char *); staticfn char *is_config_section(char *);
staticfn boolean handle_config_section(char *); staticfn boolean handle_config_section(char *);
boolean parse_config_line(char *); boolean parse_config_line(char *);
staticfn char *find_optparam(const char *); staticfn char *find_optparam(char *);
#ifndef SFCTOOL #ifndef SFCTOOL
staticfn boolean cnf_line_OPTIONS(char *); staticfn boolean cnf_line_OPTIONS(char *);
staticfn boolean cnf_line_AUTOPICKUP_EXCEPTION(char *); staticfn boolean cnf_line_AUTOPICKUP_EXCEPTION(char *);
@@ -110,6 +110,8 @@ staticfn void parse_conf_buf(struct _cnf_parser_state *parser,
boolean (*proc)(char *arg)); boolean (*proc)(char *arg));
/* next one is in extern.h; why here too? */ /* next one is in extern.h; why here too? */
boolean parse_conf_str(const char *str, boolean (*proc)(char *arg)); boolean parse_conf_str(const char *str, boolean (*proc)(char *arg));
static boolean ignore_errors_on_unmatched = FALSE,
ignore_statement_errors = FALSE;
#ifdef SFCTOOL #ifdef SFCTOOL
#ifdef wait_synch #ifdef wait_synch
@@ -242,6 +244,13 @@ fopen_config_file(const char *filename, int src)
if (filename && *filename) { if (filename && *filename) {
set_configfile_name(filename); set_configfile_name(filename);
#ifdef UNIX #ifdef UNIX
if (!strncmp(configfile, "~/", 2) && (envp = nh_getenv("HOME")) != 0) {
/* support for command line '--nethackrc=~/path' (or for
NETHACKOPTIONS='@~/path'; we don't support ~user/path) */
Snprintf(tmp_config, sizeof tmp_config, "%s/%s",
envp, configfile + 2); /* insert $HOME/ and remove ~/ */
set_configfile_name(tmp_config);
}
if (access(configfile, 4) == -1) { /* 4 is R_OK on newer systems */ if (access(configfile, 4) == -1) { /* 4 is R_OK on newer systems */
/* nasty sneaky attempt to read file through /* nasty sneaky attempt to read file through
* NetHack's setuid permissions -- this is the only * NetHack's setuid permissions -- this is the only
@@ -576,7 +585,7 @@ handle_config_section(char *buf)
/* find the '=' or ':' */ /* find the '=' or ':' */
staticfn char * staticfn char *
find_optparam(const char *buf) find_optparam(char *buf)
{ {
char *bufp, *altp; char *bufp, *altp;
@@ -1196,7 +1205,8 @@ cnf_line_SYMBOLS(char *bufp)
switch_symbols(TRUE); switch_symbols(TRUE);
return TRUE; return TRUE;
} }
config_error_add("Error in SYMBOLS definition '%s'", bufp); if (!config_unmatched_ignored())
config_error_add("Error in SYMBOLS definition '%s'", bufp);
return FALSE; return FALSE;
} }
@@ -1288,7 +1298,7 @@ typedef boolean (*config_line_stmt_func)(char *);
/* normal, alias */ /* normal, alias */
#define CNFL_NA(n, l, f) { #n, l, FALSE, FALSE, cnf_line_##f } #define CNFL_NA(n, l, f) { #n, l, FALSE, FALSE, cnf_line_##f }
/* sysconf only */ /* sysconf only */
#define CNFL_S(n, l) { #n, l, TRUE, FALSE, cnf_line_##n } #define CNFL_S(n, l) { #n, l, TRUE, FALSE, cnf_line_##n }
static const struct match_config_line_stmt { static const struct match_config_line_stmt {
const char *name; const char *name;
@@ -1373,6 +1383,8 @@ static const struct match_config_line_stmt {
#undef CNFL_NA #undef CNFL_NA
#undef CNFL_S #undef CNFL_S
static boolean disregarded_config_lines[SIZE(config_line_stmt)];
boolean boolean
parse_config_line(char *origbuf) parse_config_line(char *origbuf)
{ {
@@ -1398,7 +1410,8 @@ parse_config_line(char *origbuf)
/* find the '=' or ':' */ /* find the '=' or ':' */
bufp = find_optparam(buf); bufp = find_optparam(buf);
if (!bufp) { if (!bufp) {
config_error_add("Not a config statement, missing '='"); if (!ignore_statement_errors)
config_error_add("Not a config statement, missing '='");
return FALSE; return FALSE;
} }
/* skip past '=', then space between it and value, if any */ /* skip past '=', then space between it and value, if any */
@@ -1415,11 +1428,13 @@ parse_config_line(char *origbuf)
config_line_stmt[i].len)) { config_line_stmt[i].len)) {
char *parm = config_line_stmt[i].origbuf ? origbuf : bufp; char *parm = config_line_stmt[i].origbuf ? origbuf : bufp;
return config_line_stmt[i].fn(parm); if (!disregarded_config_lines[i])
return config_line_stmt[i].fn(parm);
} }
} }
config_error_add("Unknown config statement"); if (!ignore_errors_on_unmatched)
config_error_add("Unknown config statement");
return FALSE; return FALSE;
} }
@@ -1874,6 +1889,142 @@ vconfig_error_add(const char *str, va_list the_args)
config_erradd(buf); config_erradd(buf);
} }
#ifndef SFCTOOL
void
rcfile(void)
{
char *opts = 0, *xtraopts = 0;
const char *envname, *namesrc, *nameval;
go.opt_phase = environ_opt;
/* getenv() instead of nhgetenv(): let total length of options be long;
parseoptions() will check each individually */
envname = "NETHACKOPTIONS";
opts = getenv(envname);
if (!opts) {
/* fall back to original name; discouraged */
envname = "HACKOPTIONS";
opts = getenv(envname);
}
if (gc.cmdline_rcfile) {
namesrc = "command line";
nameval = gc.cmdline_rcfile;
xtraopts = opts;
if (opts && (*opts == '/' || *opts == '\\' || *opts == '@'))
xtraopts = 0; /* NETHACKOPTIONS is a file name; ignore it */
} else if (opts && (*opts == '/' || *opts == '\\' || *opts == '@')) {
/* NETHACKOPTIONS is a file name; use that instead of the default */
if (*opts == '@')
++opts; /* @filename */
namesrc = envname;
nameval = opts;
xtraopts = 0;
} else {
/* either no NETHACKOPTIONS or it wasn't a file name;
read the default configuration file */
nameval = namesrc = 0;
xtraopts = opts;
}
go.opt_phase = rc_file_opt;
/* seemingly arbitrary name length restriction is to prevent error
messages, if any were to be delivered while accessing the file,
from potentially overflowing buffers */
if (nameval && (int) strlen(nameval) >= BUFSZ / 2) {
config_error_init(TRUE, namesrc, FALSE);
config_error_add(
"nethackrc file name \"%.40s\"... too long; using default",
nameval);
config_error_done();
nameval = namesrc = 0; /* revert to default nethackrc */
}
config_error_init(TRUE, nameval, nameval ? CONFIG_ERROR_SECURE : FALSE);
(void) read_config_file(nameval, set_in_config);
config_error_done();
if (xtraopts) {
/* NETHACKOPTIONS is present and not a file name */
go.opt_phase = environ_opt;
config_error_init(FALSE, envname, FALSE);
(void) parseoptions(xtraopts, TRUE, FALSE);
config_error_done();
}
if (gc.cmdline_rcfile)
free((genericptr_t) gc.cmdline_rcfile), gc.cmdline_rcfile = 0;
/*[end of nethackrc handling]*/
}
void
rcfile_interface_options(void)
{
allopt_array_init();
disregard_all_options();
disregard_all_config_statements();
heed_this_option(opt_windowtype);
heed_this_option(opt_soundlib);
set_ignore_errors_on_unmatched();
ignore_statement_errors = TRUE;
rcfile();
heed_all_config_statements();
heed_all_options();
disregard_this_option(opt_windowtype);
disregard_this_option(opt_soundlib);
clear_ignore_errors_on_unmatched();
ignore_statement_errors = FALSE;
}
void
heed_all_config_statements(void)
{
int i;
for (i = 0; i < SIZE(disregarded_config_lines); i++) {
disregarded_config_lines[i] = FALSE;
}
}
void
disregard_all_config_statements(void)
{
int i;
for (i = 0; i < SIZE(disregarded_config_lines); i++) {
disregarded_config_lines[i] = TRUE;
}
}
void
heed_this_config_statement(int statement_idx)
{
if (statement_idx >= 0 && statement_idx < SIZE(disregarded_config_lines))
disregarded_config_lines[statement_idx] = FALSE;
}
void
disregard_this_config_statement(int statement_idx)
{
if (statement_idx >= 0 && statement_idx < SIZE(disregarded_config_lines))
disregarded_config_lines[statement_idx] = TRUE;
}
void
clear_ignore_errors_on_unmatched(void)
{
ignore_errors_on_unmatched = FALSE;
}
void
set_ignore_errors_on_unmatched(void)
{
ignore_errors_on_unmatched = TRUE;
}
boolean
config_unmatched_ignored(void)
{
if (ignore_errors_on_unmatched)
return TRUE;
return FALSE;
}
#endif /* SFCTOOL */
#ifdef SYSCF #ifdef SYSCF
#ifdef SYSCF_FILE #ifdef SYSCF_FILE
void void
@@ -1900,9 +2051,9 @@ assure_syscf_file(void)
#else #else
fd = open(SYSCF_FILE, O_RDONLY); fd = open(SYSCF_FILE, O_RDONLY);
#endif #endif
#else #else /* VMS */
fd = open(SYSCF_FILE, O_RDONLY, 0); fd = open(SYSCF_FILE, O_RDONLY, 0);
#endif #endif /* VMS */
if (fd >= 0) { if (fd >= 0) {
/* readable */ /* readable */
close(fd); close(fd);
+357 -123
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 cmd.c $NHDT-Date: 1736401574 2025/01/08 21:46:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.744 $ */ /* NetHack 3.7 cmd.c $NHDT-Date: 1762680996 2025/11/09 01:36:36 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.755 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -94,6 +94,10 @@ extern int dozap(void); /**/
extern int doorganize(void); /**/ extern int doorganize(void); /**/
#endif /* DUMB */ #endif /* DUMB */
staticfn struct Cmd_bind *cmdbind_get(uchar);
staticfn void cmdbind_add(uchar, const struct ext_func_tab *, boolean);
staticfn void cmdbind_remove(uchar);
staticfn void cmdbind_swapkeys(uchar, uchar);
staticfn int dosuspend_core(void); staticfn int dosuspend_core(void);
staticfn int dosh_core(void); staticfn int dosh_core(void);
staticfn int doherecmdmenu(void); staticfn int doherecmdmenu(void);
@@ -1364,6 +1368,21 @@ dolookaround(void)
return ECMD_OK; return ECMD_OK;
} }
/* #toggle extended command
BIND=':toggle(price_quotes)
BIND=@:toggle(autopickup) */
int
dotoggleoption(void)
{
if (gc.cmd_bind && gc.cmd_bind->param) {
return toggle_bool_option(gc.cmd_bind->param);
} else {
pline("Use #optionsfull to set any option instead.");
return ECMD_OK;
}
}
void void
set_move_cmd(int dir, int run) set_move_cmd(int dir, int run)
{ {
@@ -1652,26 +1671,26 @@ struct ext_func_tab extcmdlist[] = {
doextlist, IFBURIED | AUTOCOMPLETE | GENERALCMD | CMD_M_PREFIX, doextlist, IFBURIED | AUTOCOMPLETE | GENERALCMD | CMD_M_PREFIX,
NULL }, NULL },
{ M('a'), "adjust", "adjust inventory letters", { M('a'), "adjust", "adjust inventory letters",
doorganize, IFBURIED | AUTOCOMPLETE, NULL }, doorganize, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL },
{ M('A'), "annotate", "name current level", { M('A'), "annotate", "name current level",
donamelevel, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL }, donamelevel, IFBURIED | AUTOCOMPLETE | GENERALCMD | CMD_M_PREFIX, NULL },
{ 'a', "apply", "apply (use) a tool (pick-axe, key, lamp...)", { 'a', "apply", "apply (use) a tool (pick-axe, key, lamp...)",
doapply, CMD_M_PREFIX, NULL }, doapply, CMD_M_PREFIX, NULL },
{ C('x'), "attributes", "show your attributes", { C('x'), "attributes", "show your attributes",
doattributes, IFBURIED, NULL }, doattributes, IFBURIED | GENERALCMD, NULL },
{ '@', "autopickup", "toggle the 'autopickup' option on/off", { '@', "autopickup", "toggle the 'autopickup' option on/off",
dotogglepickup, IFBURIED, NULL }, dotogglepickup, IFBURIED | GENERALCMD, NULL },
#ifdef CRASHREPORT #ifdef CRASHREPORT
{ '\0', "bugreport", "file a bug report", { '\0', "bugreport", "file a bug report",
dobugreport, GENERALCMD | NOFUZZERCMD, NULL }, dobugreport, GENERALCMD | NOFUZZERCMD, NULL },
#endif #endif
{ 'C', "call", "name a monster, specific object, or type of object", { 'C', "call", "name a monster, specific object, or type of object",
docallcmd, IFBURIED, NULL }, docallcmd, IFBURIED | GENERALCMD, NULL },
{ 'Z', "cast", "zap (cast) a spell", { 'Z', "cast", "zap (cast) a spell",
docast, IFBURIED, NULL }, docast, IFBURIED, NULL },
{ M('c'), "chat", "talk to someone", { M('c'), "chat", "talk to someone",
dotalk, IFBURIED | AUTOCOMPLETE, NULL }, dotalk, IFBURIED | AUTOCOMPLETE, NULL },
{ '\0', "chronicle", "show journal of major events", { 'v', "chronicle", "show journal of major events",
do_gamelog, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL }, do_gamelog, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL },
{ 'c', "close", "close a door", { 'c', "close", "close a door",
doclose, 0, NULL }, doclose, 0, NULL },
@@ -1695,7 +1714,7 @@ struct ext_func_tab extcmdlist[] = {
{ 'E', "engrave", "engrave writing on the floor", { 'E', "engrave", "engrave writing on the floor",
doengrave, 0, NULL }, doengrave, 0, NULL },
{ M('e'), "enhance", "advance or check weapon and spell skills", { M('e'), "enhance", "advance or check weapon and spell skills",
enhance_weapon_skill, IFBURIED | AUTOCOMPLETE, NULL }, enhance_weapon_skill, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL },
/* #exploremode should be flagged AUTOCOMPETE but that would negatively /* #exploremode should be flagged AUTOCOMPETE but that would negatively
impact frequently used #enhance by making #e become ambiguous */ impact frequently used #enhance by making #e become ambiguous */
{ M('X'), "exploremode", "enter explore (discovery) mode", { M('X'), "exploremode", "enter explore (discovery) mode",
@@ -1716,12 +1735,12 @@ struct ext_func_tab extcmdlist[] = {
dohelp, IFBURIED | GENERALCMD, NULL }, dohelp, IFBURIED | GENERALCMD, NULL },
{ '\0', "herecmdmenu", "show menu of commands you can do here", { '\0', "herecmdmenu", "show menu of commands you can do here",
doherecmdmenu, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL }, doherecmdmenu, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL },
{ 'V', "history", "show long version and game history", { '\0', "history", "show long version and game history",
dohistory, IFBURIED | GENERALCMD, NULL }, dohistory, IFBURIED | GENERALCMD, NULL },
{ 'i', "inventory", "show your inventory", { 'i', "inventory", "show your inventory",
ddoinv, IFBURIED, NULL }, ddoinv, IFBURIED | GENERALCMD, NULL },
{ 'I', "inventtype", "show inventory of one specific item class", { 'I', "inventtype", "show inventory of one specific item class",
dotypeinv, IFBURIED, NULL }, dotypeinv, IFBURIED | GENERALCMD, NULL },
{ M('i'), "invoke", "invoke an object's special powers", { M('i'), "invoke", "invoke an object's special powers",
doinvoke, IFBURIED | AUTOCOMPLETE, NULL }, doinvoke, IFBURIED | AUTOCOMPLETE, NULL },
{ M('j'), "jump", "jump to another location", { M('j'), "jump", "jump to another location",
@@ -1752,7 +1771,7 @@ struct ext_func_tab extcmdlist[] = {
{ M('m'), "monster", "use monster's special ability", { M('m'), "monster", "use monster's special ability",
domonability, IFBURIED | AUTOCOMPLETE, NULL }, domonability, IFBURIED | AUTOCOMPLETE, NULL },
{ M('n'), "name", "same as call; name a monster or object or object type", { M('n'), "name", "same as call; name a monster or object or object type",
docallcmd, IFBURIED | AUTOCOMPLETE, NULL }, docallcmd, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL },
{ M('o'), "offer", "offer a sacrifice to the gods", { M('o'), "offer", "offer a sacrifice to the gods",
dosacrifice, AUTOCOMPLETE | CMD_M_PREFIX, NULL }, dosacrifice, AUTOCOMPLETE | CMD_M_PREFIX, NULL },
{ 'o', "open", "open a door", { 'o', "open", "open a door",
@@ -1827,17 +1846,17 @@ struct ext_func_tab extcmdlist[] = {
{ 's', "search", "search for traps and secret doors", { 's', "search", "search for traps and secret doors",
dosearch, IFBURIED | CMD_M_PREFIX, "searching" }, dosearch, IFBURIED | CMD_M_PREFIX, "searching" },
{ '*', "seeall", "show all equipment in use", { '*', "seeall", "show all equipment in use",
doprinuse, IFBURIED | CMD_M_PREFIX, NULL }, doprinuse, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ AMULET_SYM, "seeamulet", "show the amulet currently worn", { AMULET_SYM, "seeamulet", "show the amulet currently worn",
dopramulet, IFBURIED | CMD_M_PREFIX, NULL }, dopramulet, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ ARMOR_SYM, "seearmor", "show the armor currently worn", { ARMOR_SYM, "seearmor", "show the armor currently worn",
doprarm, IFBURIED | CMD_M_PREFIX, NULL }, doprarm, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ RING_SYM, "seerings", "show the ring(s) currently worn", { RING_SYM, "seerings", "show the ring(s) currently worn",
doprring, IFBURIED | CMD_M_PREFIX, NULL }, doprring, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ TOOL_SYM, "seetools", "show the tools currently in use", { TOOL_SYM, "seetools", "show the tools currently in use",
doprtool, IFBURIED | CMD_M_PREFIX, NULL }, doprtool, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ WEAPON_SYM, "seeweapon", "show the weapon currently wielded", { WEAPON_SYM, "seeweapon", "show the weapon currently wielded",
doprwep, IFBURIED | CMD_M_PREFIX, NULL }, doprwep, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ '!', "shell", { '!', "shell",
"leave game to enter a sub-shell ('exit' to come back)", "leave game to enter a sub-shell ('exit' to come back)",
dosh_core, (IFBURIED | GENERALCMD | NOFUZZERCMD dosh_core, (IFBURIED | GENERALCMD | NOFUZZERCMD
@@ -1847,11 +1866,11 @@ struct ext_func_tab extcmdlist[] = {
), NULL }, ), NULL },
/* $ is like ),=,&c but is not included with *, so not called "seegold" */ /* $ is like ),=,&c but is not included with *, so not called "seegold" */
{ GOLD_SYM, "showgold", "show gold, possibly shop credit or debt", { GOLD_SYM, "showgold", "show gold, possibly shop credit or debt",
doprgold, IFBURIED | CMD_M_PREFIX, NULL }, doprgold, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ SPBOOK_SYM, "showspells", "list and reorder known spells", { SPBOOK_SYM, "showspells", "list and reorder known spells",
dovspell, IFBURIED, NULL }, dovspell, IFBURIED | GENERALCMD, NULL },
{ '^', "showtrap", "describe an adjacent, discovered trap", { '^', "showtrap", "describe an adjacent, discovered trap",
doidtrap, IFBURIED, NULL }, doidtrap, IFBURIED | GENERALCMD, NULL },
{ M('s'), "sit", "sit down", { M('s'), "sit", "sit down",
dosit, AUTOCOMPLETE, NULL }, dosit, AUTOCOMPLETE, NULL },
{ '\0', "stats", "show memory statistics", { '\0', "stats", "show memory statistics",
@@ -1875,7 +1894,7 @@ struct ext_func_tab extcmdlist[] = {
<delete> it may or may not actually invoke the #terrain command */ <delete> it may or may not actually invoke the #terrain command */
{ '\177', "terrain", { '\177', "terrain",
"view map without monsters or objects obstructing it", "view map without monsters or objects obstructing it",
doterrain, IFBURIED | AUTOCOMPLETE, NULL }, doterrain, IFBURIED | GENERALCMD | AUTOCOMPLETE, NULL },
{ '\0', "therecmdmenu", { '\0', "therecmdmenu",
"menu of commands you can do from here to adjacent spot", "menu of commands you can do from here to adjacent spot",
dotherecmdmenu, AUTOCOMPLETE | GENERALCMD | MOUSECMD, NULL }, dotherecmdmenu, AUTOCOMPLETE | GENERALCMD | MOUSECMD, NULL },
@@ -1885,6 +1904,8 @@ struct ext_func_tab extcmdlist[] = {
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ M('T'), "tip", "empty a container", { M('T'), "tip", "empty a container",
dotip, AUTOCOMPLETE | CMD_M_PREFIX, NULL }, dotip, AUTOCOMPLETE | CMD_M_PREFIX, NULL },
{ '\0', "toggle", "toggle boolean option",
dotoggleoption, IFBURIED | GENERALCMD | CMD_PARAM, NULL },
{ '_', "travel", "travel to a specific location on the map", { '_', "travel", "travel to a specific location on the map",
dotravel, CMD_M_PREFIX, NULL }, dotravel, CMD_M_PREFIX, NULL },
{ M('t'), "turn", "turn undead away", { M('t'), "turn", "turn undead away",
@@ -1902,8 +1923,8 @@ struct ext_func_tab extcmdlist[] = {
{ M('v'), "version", { M('v'), "version",
"list compile time options for this version of NetHack", "list compile time options for this version of NetHack",
doextversion, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL }, doextversion, IFBURIED | AUTOCOMPLETE | GENERALCMD, NULL },
{ 'v', "versionshort", "show version and date+time program was built", { 'V', "versionshort", "show version and date+time program was built",
doversion, IFBURIED | GENERALCMD, NULL }, doversion, IFBURIED | GENERALCMD | CMD_M_PREFIX, NULL },
{ '\0', "vision", "show vision array", { '\0', "vision", "show vision array",
wiz_show_vision, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, wiz_show_vision, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ '.', "wait", "rest one move while doing nothing", { '.', "wait", "rest one move while doing nothing",
@@ -1911,7 +1932,7 @@ struct ext_func_tab extcmdlist[] = {
{ 'W', "wear", "wear a piece of armor", { 'W', "wear", "wear a piece of armor",
dowear, 0, NULL }, dowear, 0, NULL },
{ '&', "whatdoes", "tell what a command does", { '&', "whatdoes", "tell what a command does",
dowhatdoes, IFBURIED, NULL }, dowhatdoes, IFBURIED | GENERALCMD, NULL },
{ '/', "whatis", "show what type of thing a symbol corresponds to", { '/', "whatis", "show what type of thing a symbol corresponds to",
dowhatis, IFBURIED | GENERALCMD, NULL }, dowhatis, IFBURIED | GENERALCMD, NULL },
{ 'w', "wield", "wield (put in use) a weapon", { 'w', "wield", "wield (put in use) a weapon",
@@ -1952,6 +1973,10 @@ struct ext_func_tab extcmdlist[] = {
wiz_load_splua, IFBURIED | WIZMODECMD | NOFUZZERCMD, NULL }, wiz_load_splua, IFBURIED | WIZMODECMD | NOFUZZERCMD, NULL },
{ '\0', "wizloadlua", "load and execute a lua script", { '\0', "wizloadlua", "load and execute a lua script",
wiz_load_lua, IFBURIED | WIZMODECMD | NOFUZZERCMD, NULL }, wiz_load_lua, IFBURIED | WIZMODECMD | NOFUZZERCMD, NULL },
#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG)
{ '\0', "wizobjprobs", "list object generation probabilities",
wiz_objprobs, IFBURIED | WIZMODECMD, NULL },
#endif
{ '\0', "wizmakemap", "recreate the current level", { '\0', "wizmakemap", "recreate the current level",
wiz_makemap, IFBURIED | WIZMODECMD, NULL }, wiz_makemap, IFBURIED | WIZMODECMD, NULL },
{ C('f'), "wizmap", "map the level", { C('f'), "wizmap", "map the level",
@@ -1971,7 +1996,7 @@ struct ext_func_tab extcmdlist[] = {
{ '\0', "wizwhere", "show locations of special levels", { '\0', "wizwhere", "show locations of special levels",
wiz_where, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, wiz_where, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ C('w'), "wizwish", "wish for something", { C('w'), "wizwish", "wish for something",
wiz_wish, IFBURIED | WIZMODECMD, NULL }, wiz_wish, IFBURIED | CMD_M_PREFIX | WIZMODECMD, NULL },
{ '\0', "wmode", "show wall modes", { '\0', "wmode", "show wall modes",
wiz_show_wmodes, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, wiz_show_wmodes, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ 'z', "zap", "zap a wand", { 'z', "zap", "zap a wand",
@@ -2032,8 +2057,9 @@ struct ext_func_tab extcmdlist[] = {
/* internal commands: only used by game core, not available for user */ /* internal commands: only used by game core, not available for user */
{ '\0', "clicklook", NULL, doclicklook, INTERNALCMD | MOUSECMD, NULL }, { '\0', "clicklook", NULL, doclicklook, INTERNALCMD | MOUSECMD, NULL },
{ '\0', "mouseaction", NULL, domouseaction, INTERNALCMD | MOUSECMD, NULL }, { '\0', "mouseaction", NULL, domouseaction, INTERNALCMD | MOUSECMD, NULL },
{ '\0', "altdip", NULL, dip_into, INTERNALCMD, NULL },
{ '\0', "altadjust", NULL, adjust_split, INTERNALCMD, NULL }, { '\0', "altadjust", NULL, adjust_split, INTERNALCMD, NULL },
{ '\0', "altdip", NULL, dip_into, INTERNALCMD, NULL },
{ '\0', "alttakeoff", NULL, ia_dotakeoff, INTERNALCMD, NULL },
{ '\0', "altunwield", NULL, remarm_swapwep, INTERNALCMD, NULL }, { '\0', "altunwield", NULL, remarm_swapwep, INTERNALCMD, NULL },
{ '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */ { '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */
}; };
@@ -2077,17 +2103,128 @@ extcmds_getentry(int i)
return &extcmdlist[i]; return &extcmdlist[i];
} }
/* get the command bound to a key */
staticfn struct Cmd_bind *
cmdbind_get(uchar key)
{
struct Cmd_bind *bind = gc.Cmd.cmdbinds;
if (!key)
return NULL;
while (bind) {
if (bind->key == key)
return bind;
bind = bind->next;
}
return bind;
}
staticfn void
cmdbind_add(uchar key, const struct ext_func_tab *extcmd, boolean user)
{
struct Cmd_bind *bind = cmdbind_get(key);
if (!key)
return;
if (!extcmd && bind) {
cmdbind_remove(key);
return;
}
/* binding exists, set it to this command */
if (bind) {
bind->cmd = extcmd;
bind->userbind = user;
if (bind->param) {
free(bind->param);
bind->param = NULL;
}
return;
} else {
bind = (struct Cmd_bind *) alloc(sizeof(struct Cmd_bind));
bind->key = key;
bind->userbind = user;
bind->param = NULL;
bind->cmd = extcmd;
bind->next = gc.Cmd.cmdbinds;
gc.Cmd.cmdbinds = bind;
}
}
staticfn void
cmdbind_remove(uchar key)
{
struct Cmd_bind *bind = gc.Cmd.cmdbinds;
struct Cmd_bind *prev = (struct Cmd_bind *) 0;
while (bind) {
if (bind->key == key) {
if (prev)
prev->next = bind->next;
else
gc.Cmd.cmdbinds = bind->next;
if (bind->param)
free(bind->param);
free(bind);
return;
}
prev = bind;
bind = bind->next;
}
}
void
cmdbind_freeall(void)
{
struct Cmd_bind *next;
while (gc.Cmd.cmdbinds) {
next = gc.Cmd.cmdbinds->next;
if (gc.Cmd.cmdbinds->param)
free(gc.Cmd.cmdbinds->param);
free(gc.Cmd.cmdbinds);
gc.Cmd.cmdbinds = next;
}
}
/* swap key bindings for key1 and key2. both bindings must exist. */
staticfn void
cmdbind_swapkeys(uchar key1, uchar key2)
{
struct Cmd_bind *bind1 = cmdbind_get(key1);
struct Cmd_bind *bind2 = cmdbind_get(key2);
if (bind1 && bind2) {
bind1->key = key2;
bind2->key = key1;
}
}
/* return number of extended commands bound to a non-default key */ /* return number of extended commands bound to a non-default key */
int int
count_bind_keys(void) count_bind_keys(void)
{ {
int nbinds = 0; struct Cmd_bind *bind = gc.Cmd.cmdbinds;
int i; int i, nbinds = 0;
uchar keys[256];
for (i = 0; i < extcmdlist_length; i++) (void) memset(keys, 0, sizeof(uchar) * 256);
if (extcmdlist[i].key
&& gc.Cmd.commands[extcmdlist[i].key] != &extcmdlist[i]) /* commands bound to different key */
while (bind) {
keys[bind->key] = 1;
if (bind->userbind && bind->cmd && bind->cmd->key != bind->key) {
nbinds++; nbinds++;
}
bind = bind->next;
}
/* commands which should be bound to a key, but aren't */
for (i = 0; i < extcmdlist_length; i++)
if (extcmdlist[i].key && !keys[extcmdlist[i].key])
nbinds++;
return nbinds; return nbinds;
} }
@@ -2099,16 +2236,41 @@ get_changed_key_binds(strbuf_t *sbuf)
int i; int i;
char buf[BUFSZ]; char buf[BUFSZ];
char buf2[QBUFSZ]; char buf2[QBUFSZ];
struct Cmd_bind *bind = gc.Cmd.cmdbinds;
uchar keys[256];
(void) memset(keys, 0, sizeof(uchar) * 256);
if (!sbuf) if (!sbuf)
win = create_nhwindow(NHW_TEXT); win = create_nhwindow(NHW_TEXT);
/* commands bound to different key */
while (bind) {
keys[bind->key] = 1;
if (bind->userbind && bind->cmd && bind->cmd->key != bind->key) {
if ((bind->cmd->flags & CMD_PARAM) != 0)
Sprintf(buf, "BIND=%s:%s(%s)%s", key2txt(bind->key, buf2),
bind->cmd->ef_txt,
bind->param,
sbuf ? "\n" : "");
else
Sprintf(buf, "BIND=%s:%s%s", key2txt(bind->key, buf2),
bind->cmd->ef_txt,
sbuf ? "\n" : "");
if (sbuf)
strbuf_append(sbuf, buf);
else
putstr(win, 0, buf);
}
bind = bind->next;
}
/* commands which should be bound to a key, but aren't */
for (i = 0; i < extcmdlist_length; i++) { for (i = 0; i < extcmdlist_length; i++) {
struct ext_func_tab *ec = &extcmdlist[i]; struct ext_func_tab *ec = &extcmdlist[i];
if (ec->key && gc.Cmd.commands[ec->key] if (ec->key && !keys[ec->key]) {
&& gc.Cmd.commands[ec->key] != ec) { Sprintf(buf, "BIND=%s:nothing%s", key2txt(ec->key, buf2),
Sprintf(buf, "BIND=%s:%s%s", key2txt(ec->key, buf2),
gc.Cmd.commands[ec->key]->ef_txt,
sbuf ? "\n" : ""); sbuf ? "\n" : "");
if (sbuf) if (sbuf)
strbuf_append(sbuf, buf); strbuf_append(sbuf, buf);
@@ -2149,9 +2311,11 @@ handler_rebind_keys_add(boolean keyfirst)
any = cg.zeroany; any = cg.zeroany;
if (key) { if (key) {
if (gc.Cmd.commands[key]) { struct Cmd_bind *bind = cmdbind_get(key);
if (bind && bind->cmd) {
Sprintf(buf, "Key '%s' is currently bound to \"%s\".", Sprintf(buf, "Key '%s' is currently bound to \"%s\".",
key2txt(key, buf2), gc.Cmd.commands[key]->ef_txt); key2txt(key, buf2), bind->cmd->ef_txt);
} else { } else {
Sprintf(buf, "Key '%s' is not bound to anything.", Sprintf(buf, "Key '%s' is not bound to anything.",
key2txt(key, buf2)); key2txt(key, buf2));
@@ -2186,19 +2350,32 @@ handler_rebind_keys_add(boolean keyfirst)
npick = select_menu(win, PICK_ONE, &picks); npick = select_menu(win, PICK_ONE, &picks);
destroy_nhwindow(win); destroy_nhwindow(win);
if (npick > 0) { if (npick > 0) {
const struct ext_func_tab *prevec; struct Cmd_bind *prevcmd;
const char *cmdstr; char cmdstr[BUFSZ];
i = picks->item.a_int; i = picks->item.a_int;
free((genericptr_t) picks); free((genericptr_t) picks);
if (i == -1) { if (i == -1) {
ec = NULL; ec = NULL;
cmdstr = "nothing"; Strcat(cmdstr, "nothing");
goto bindit; goto bindit;
} else { } else {
ec = &extcmdlist[i-1]; ec = &extcmdlist[i-1];
cmdstr = ec->ef_txt;
if ((ec->flags & CMD_PARAM) != 0) {
char parambuf[BUFSZ];
char querybuf[BUFSZ];
parambuf[0] = '\0';
Sprintf(querybuf, "Command %s requires a parameter:", ec->ef_txt);
getlin(querybuf, parambuf);
(void) mungspaces(parambuf);
Snprintf(cmdstr, BUFSZ-1, "%s(%s)", ec->ef_txt, parambuf);
cmdstr[BUFSZ-1] = '\0';
} else {
Strcat(cmdstr, ec->ef_txt);
}
} }
bindit: bindit:
if (!key) { if (!key) {
@@ -2209,13 +2386,13 @@ handler_rebind_keys_add(boolean keyfirst)
return; return;
} }
prevec = gc.Cmd.commands[key]; prevcmd = cmdbind_get(key);
if (bind_key(key, cmdstr)) { if (bind_key(key, cmdstr, TRUE)) {
if (prevec && prevec != ec) { if (prevcmd && prevcmd->cmd != ec) {
pline("Changed key '%s' from \"%s\" to \"%s\".", pline("Changed key '%s' from \"%s\" to \"%s\".",
key2txt(key, buf2), prevec->ef_txt, cmdstr); key2txt(key, buf2), prevcmd->cmd->ef_txt, cmdstr);
} else if (!prevec) { } else if (!prevcmd) {
pline("Bound key '%s' to \"%s\".", pline("Bound key '%s' to \"%s\".",
key2txt(key, buf2), cmdstr); key2txt(key, buf2), cmdstr);
} }
@@ -2385,6 +2562,7 @@ key2extcmddesc(uchar key)
const char *txt; const char *txt;
int k, i, j; int k, i, j;
uchar M_5 = (uchar) M('5'), M_0 = (uchar) M('0'); uchar M_5 = (uchar) M('5'), M_0 = (uchar) M('0');
struct Cmd_bind *cmdbind;
/* need to check for movement commands before checking the extended /* need to check for movement commands before checking the extended
commands table because it contains entries for number_pad commands commands table because it contains entries for number_pad commands
@@ -2417,8 +2595,10 @@ key2extcmddesc(uchar key)
return misc_keys[i].desc; return misc_keys[i].desc;
} }
/* finally, check whether 'key' is a command */ /* finally, check whether 'key' is a command */
if (gc.Cmd.commands[key] && (txt = gc.Cmd.commands[key]->ef_txt) != 0) { if ((cmdbind = cmdbind_get(key)) != 0
Sprintf(key2cmdbuf, "%s (#%s)", gc.Cmd.commands[key]->ef_desc, txt); && cmdbind->cmd
&& (txt = cmdbind->cmd->ef_txt) != 0) {
Sprintf(key2cmdbuf, "%s (#%s)", cmdbind->cmd->ef_desc, txt);
/* special case: for reqmenu prefix (normally 'm'), replace /* special case: for reqmenu prefix (normally 'm'), replace
"prefix: request menu or modify command (#reqmenu)" "prefix: request menu or modify command (#reqmenu)"
@@ -2477,22 +2657,58 @@ bind_mousebtn(int btn, const char *command)
} }
boolean boolean
bind_key(uchar key, const char *command) bind_key(uchar key, const char *command, boolean user)
{ {
struct ext_func_tab *extcmd; struct ext_func_tab *extcmd;
long len;
char *buf, *p = NULL, *lastp = NULL;
/* special case: "nothing" is reserved for unbinding */ /* special case: "nothing" is reserved for unbinding */
if (!strcmpi(command, "nothing")) { if (!strcmpi(command, "nothing")) {
gc.Cmd.commands[key] = (struct ext_func_tab *) 0; cmdbind_remove(key);
return TRUE; return TRUE;
} }
/* copy command to buf for modification */
len = strlen(command) + 1;
buf = (char *)alloc(len);
(void) strncpy(buf, command, len);
/* does buf have a parameter in parenthesis? */
if ((p = strchr(buf, '(')) != 0
&& (lastp = strrchr(buf, ')')) != 0
&& (lastp > p)) {
*p = '\0';
*lastp = '\0';
/* p points to the parameter */
p++;
}
for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) { for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
if (strcmpi(command, extcmd->ef_txt)) if (strcmpi(buf, extcmd->ef_txt))
continue; continue;
if ((extcmd->flags & INTERNALCMD) != 0) if ((extcmd->flags & INTERNALCMD) != 0)
continue; continue;
gc.Cmd.commands[key] = extcmd; cmdbind_add(key, extcmd, user);
if ((extcmd->flags & CMD_PARAM) != 0) {
if (!p) {
config_error_add("'%s' requires a parameter", buf);
} else {
struct Cmd_bind *bind = cmdbind_get(key);
int maxlen = min(30, strlen(p)) + 1;
if (maxlen <= 1) {
config_error_add("Required parameter cannot be empty");
} else {
bind->param = (char *) alloc(maxlen);
(void) strncpy(bind->param, p, maxlen);
bind->param[maxlen-1] = '\0';
}
}
} else if (p && strlen(p) > 0)
config_error_add("'%s' does not take a parameter", buf);
#if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */ #if 0 /* silently accept key binding for unavailable command (!SHELL,&c) */
if ((extcmd->flags & CMD_NOT_AVAILABLE) != 0) { if ((extcmd->flags & CMD_NOT_AVAILABLE) != 0) {
char buf[BUFSZ]; char buf[BUFSZ];
@@ -2501,9 +2717,11 @@ bind_key(uchar key, const char *command)
config_error_add("%s", buf); config_error_add("%s", buf);
} }
#endif #endif
free(buf);
return TRUE; return TRUE;
} }
free(buf);
return FALSE; return FALSE;
} }
@@ -2518,7 +2736,7 @@ bind_key_fn(uchar key, int (*fn)(void))
continue; continue;
if ((extcmd->flags & INTERNALCMD) != 0) if ((extcmd->flags & INTERNALCMD) != 0)
continue; continue;
gc.Cmd.commands[key] = extcmd; cmdbind_add(key, extcmd, FALSE);
return TRUE; return TRUE;
} }
@@ -2533,31 +2751,31 @@ commands_init(void)
for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++)
if (extcmd->key) if (extcmd->key)
gc.Cmd.commands[extcmd->key] = extcmd; cmdbind_add(extcmd->key, extcmd, FALSE);
(void) bind_mousebtn(1, "therecmdmenu"); (void) bind_mousebtn(1, "therecmdmenu");
(void) bind_mousebtn(2, "clicklook"); (void) bind_mousebtn(2, "clicklook");
/* number_pad */ /* number_pad */
(void) bind_key(C('l'), "redraw"); (void) bind_key(C('l'), "redraw", FALSE);
(void) bind_key('h', "help"); (void) bind_key('h', "help", FALSE);
(void) bind_key('j', "jump"); (void) bind_key('j', "jump", FALSE);
(void) bind_key('k', "kick"); (void) bind_key('k', "kick", FALSE);
(void) bind_key('l', "loot"); (void) bind_key('l', "loot", FALSE);
(void) bind_key(C('n'), "annotate"); (void) bind_key(C('n'), "annotate", FALSE);
(void) bind_key('N', "name"); (void) bind_key('N', "name", FALSE);
(void) bind_key('u', "untrap"); (void) bind_key('u', "untrap", FALSE);
(void) bind_key('5', "run"); (void) bind_key('5', "run", FALSE);
(void) bind_key(M('5'), "rush"); (void) bind_key(M('5'), "rush", FALSE);
(void) bind_key('-', "fight"); (void) bind_key('-', "fight", FALSE);
/* alt keys: */ /* alt keys: */
(void) bind_key(M('O'), "overview"); (void) bind_key(M('O'), "overview", FALSE);
(void) bind_key(M('2'), "twoweapon"); (void) bind_key(M('2'), "twoweapon", FALSE);
(void) bind_key(M('N'), "name"); (void) bind_key(M('N'), "name", FALSE);
#if 0 #if 0
/* don't do this until the rest_on_space option is set or cleared */ /* don't do this until the rest_on_space option is set or cleared */
(void) bind_key(' ', "wait"); (void) bind_key(' ', "wait", FALSE);
#endif #endif
} }
@@ -2566,12 +2784,13 @@ keylist_func_has_key(const struct ext_func_tab *extcmd,
boolean *skip_keys_used) /* boolean keys_used[256] */ boolean *skip_keys_used) /* boolean keys_used[256] */
{ {
int i; int i;
struct Cmd_bind *bind;
for (i = 0; i < 256; ++i) { for (i = 0; i < 256; ++i) {
if (skip_keys_used[i]) if (skip_keys_used[i])
continue; continue;
if (gc.Cmd.commands[i] == extcmd) if (((bind = cmdbind_get(i)) != 0) && (bind->cmd == extcmd))
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@@ -2587,6 +2806,7 @@ keylist_putcmds(winid datawin, boolean docount,
char buf[BUFSZ], buf2[QBUFSZ]; char buf[BUFSZ], buf2[QBUFSZ];
boolean keys_already_used[256]; /* copy of keys_used[] before updates */ boolean keys_already_used[256]; /* copy of keys_used[] before updates */
int count = 0; int count = 0;
struct Cmd_bind *bind;
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
uchar key = (uchar) i; uchar key = (uchar) i;
@@ -2596,16 +2816,22 @@ keylist_putcmds(winid datawin, boolean docount,
continue; continue;
if (key == ' ' && !flags.rest_on_space) if (key == ' ' && !flags.rest_on_space)
continue; continue;
if ((extcmd = gc.Cmd.commands[i]) != (struct ext_func_tab *) 0) { bind = cmdbind_get(key);
if ((incl_flags && !(extcmd->flags & incl_flags)) if (bind && bind->cmd != (struct ext_func_tab *) 0) {
|| (excl_flags && (extcmd->flags & excl_flags))) if ((incl_flags && !(bind->cmd->flags & incl_flags))
|| (excl_flags && (bind->cmd->flags & excl_flags)))
continue; continue;
if (docount) { if (docount) {
count++; count++;
continue; continue;
} }
Sprintf(buf, "%-7s %-13s %s", key2txt(key, buf2), if ((bind->cmd->flags & CMD_PARAM) != 0)
extcmd->ef_txt, extcmd->ef_desc); Sprintf(buf, "%-7s %-13s %s \"%s\"", key2txt(key, buf2),
bind->cmd->ef_txt, bind->cmd->ef_desc,
bind->param);
else
Sprintf(buf, "%-7s %-13s %s", key2txt(key, buf2),
bind->cmd->ef_txt, bind->cmd->ef_desc);
putstr(datawin, 0, buf); putstr(datawin, 0, buf);
keys_used[i] = TRUE; keys_used[i] = TRUE;
} }
@@ -2809,9 +3035,10 @@ cmd_from_func(int (*fn)(void))
{ {
int i; int i;
char ret = '\0'; char ret = '\0';
struct Cmd_bind *bind;
/* skip NUL; allowing it would wreak havoc */ for (bind = gc.Cmd.cmdbinds; bind; bind = bind->next) {
for (i = 1; i < 256; ++i) { i = bind->key;
/* skip space; we'll use it below as last resort if no other /* skip space; we'll use it below as last resort if no other
keystroke invokes space's command */ keystroke invokes space's command */
if (i == ' ') if (i == ' ')
@@ -2822,7 +3049,7 @@ cmd_from_func(int (*fn)(void))
&& !gc.Cmd.num_pad) && !gc.Cmd.num_pad)
continue; continue;
if (gc.Cmd.commands[i] && gc.Cmd.commands[i]->ef_funct == fn) { if (bind->cmd && bind->cmd->ef_funct == fn) {
if (i >= ' ' && i <= '~') if (i >= ' ' && i <= '~')
return (char) i; return (char) i;
else { else {
@@ -2830,7 +3057,8 @@ cmd_from_func(int (*fn)(void))
} }
} }
} }
if (gc.Cmd.commands[' '] && gc.Cmd.commands[' ']->ef_funct == fn) if ((bind = cmdbind_get(' ')) != 0 && bind->cmd
&& bind->cmd->ef_funct == fn)
return ' '; return ' ';
return ret; return ret;
} }
@@ -3123,7 +3351,6 @@ reset_commands(boolean initial)
static struct ext_func_tab *back_dir_cmd[N_DIRS][N_MOVEMODES]; static struct ext_func_tab *back_dir_cmd[N_DIRS][N_MOVEMODES];
static uchar back_dir_key[N_DIRS][N_MOVEMODES]; static uchar back_dir_key[N_DIRS][N_MOVEMODES];
static boolean backed_dir_cmd = FALSE; static boolean backed_dir_cmd = FALSE;
const struct ext_func_tab *cmdtmp;
boolean flagtemp; boolean flagtemp;
int c, i, updated = 0; int c, i, updated = 0;
int dir, mode; int dir, mode;
@@ -3139,8 +3366,7 @@ reset_commands(boolean initial)
if (backed_dir_cmd) { if (backed_dir_cmd) {
for (dir = 0; dir < N_DIRS; dir++) { for (dir = 0; dir < N_DIRS; dir++) {
for (mode = 0; mode < N_MOVEMODES; mode++) { for (mode = 0; mode < N_MOVEMODES; mode++) {
gc.Cmd.commands[back_dir_key[dir][mode]] cmdbind_add(back_dir_key[dir][mode], back_dir_cmd[dir][mode], FALSE);
= back_dir_cmd[dir][mode];
} }
} }
} }
@@ -3162,9 +3388,7 @@ reset_commands(boolean initial)
perform the swap (or reverse previous one) */ perform the swap (or reverse previous one) */
for (i = 0; i < SIZE(ylist); i++) { for (i = 0; i < SIZE(ylist); i++) {
c = ylist[i] & 0xff; c = ylist[i] & 0xff;
cmdtmp = gc.Cmd.commands[c]; /* tmp = [y] */ cmdbind_swapkeys(c, c + 1);
gc.Cmd.commands[c] = gc.Cmd.commands[c + 1]; /* [y] = [z] */
gc.Cmd.commands[c + 1] = cmdtmp; /* [z] = tmp */
} }
} }
/* MSDOS compatibility mode (only applicable for num_pad) */ /* MSDOS compatibility mode (only applicable for num_pad) */
@@ -3181,8 +3405,10 @@ reset_commands(boolean initial)
#endif #endif
/* FIXME: NHKF_DOINV2 ought to be implemented instead of this */ /* FIXME: NHKF_DOINV2 ought to be implemented instead of this */
c = M('0') & 0xff; c = M('0') & 0xff;
gc.Cmd.commands[c] = gc.Cmd.pcHack_compat ? gc.Cmd.commands['I'] if (gc.Cmd.pcHack_compat)
: 0; cmdbind_add(c, ext_func_tab_from_func(dotypeinv), FALSE);
else
cmdbind_remove(c);
} }
/* phone keypad layout (only applicable for num_pad) */ /* phone keypad layout (only applicable for num_pad) */
flagtemp = (iflags.num_pad_mode & 2) ? gc.Cmd.num_pad : FALSE; flagtemp = (iflags.num_pad_mode & 2) ? gc.Cmd.num_pad : FALSE;
@@ -3192,13 +3418,9 @@ reset_commands(boolean initial)
/* phone_layout has been toggled */ /* phone_layout has been toggled */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
c = '1' + i; /* 1,2,3 <-> 7,8,9 */ c = '1' + i; /* 1,2,3 <-> 7,8,9 */
cmdtmp = gc.Cmd.commands[c]; /* tmp = [1] */ cmdbind_swapkeys(c, c + 6);
gc.Cmd.commands[c] = gc.Cmd.commands[c + 6]; /* [1] = [7] */
gc.Cmd.commands[c + 6] = cmdtmp; /* [7] = tmp */
c = (M('1') & 0xff) + i; /* M-1,M-2,M-3 <-> M-7,M-8,M-9 */ c = (M('1') & 0xff) + i; /* M-1,M-2,M-3 <-> M-7,M-8,M-9 */
cmdtmp = gc.Cmd.commands[c]; /* tmp = [M-1] */ cmdbind_swapkeys(c, c + 6);
gc.Cmd.commands[c] = gc.Cmd.commands[c + 6]; /* [M-1]=[M-7] */
gc.Cmd.commands[c + 6] = cmdtmp; /* [M-7] = tmp */
} }
} }
} /*?initial*/ } /*?initial*/
@@ -3215,6 +3437,7 @@ reset_commands(boolean initial)
for (dir = 0; dir < N_DIRS; dir++) { for (dir = 0; dir < N_DIRS; dir++) {
for (mode = MV_WALK; mode < N_MOVEMODES; mode++) { for (mode = MV_WALK; mode < N_MOVEMODES; mode++) {
uchar di = (uchar) gc.Cmd.dirchars[dir]; uchar di = (uchar) gc.Cmd.dirchars[dir];
struct Cmd_bind *bind;
if (!gc.Cmd.num_pad) { if (!gc.Cmd.num_pad) {
if (mode == MV_RUN) di = highc(di); if (mode == MV_RUN) di = highc(di);
@@ -3224,9 +3447,11 @@ reset_commands(boolean initial)
else if (mode == MV_RUSH) di = M(di); else if (mode == MV_RUSH) di = M(di);
} }
back_dir_key[dir][mode] = di; back_dir_key[dir][mode] = di;
back_dir_cmd[dir][mode] if ((bind = cmdbind_get(di)) != 0)
= (struct ext_func_tab *) gc.Cmd.commands[di]; back_dir_cmd[dir][mode] = (struct ext_func_tab *) bind->cmd;
gc.Cmd.commands[di] = (struct ext_func_tab *) 0; else
back_dir_cmd[dir][mode] = (struct ext_func_tab *) 0;
cmdbind_remove(di);
} }
} }
backed_dir_cmd = TRUE; backed_dir_cmd = TRUE;
@@ -3264,15 +3489,15 @@ update_rest_on_space(void)
donull, (IFBURIED | CMD_M_PREFIX), "waiting" donull, (IFBURIED | CMD_M_PREFIX), "waiting"
}; };
static const struct ext_func_tab *unrestonspace = 0; static const struct ext_func_tab *unrestonspace = 0;
const struct ext_func_tab *bound_f = gc.Cmd.commands[' ']; struct Cmd_bind *bind = cmdbind_get(' ');
/* when 'rest_on_space' is On, <space> will run the #wait command; /* when 'rest_on_space' is On, <space> will run the #wait command;
when it is Off, <space> will use 'unrestonspace' which will either when it is Off, <space> will use 'unrestonspace' which will either
be Null and elicit "Unknown command ' '." or have some non-Null be Null and elicit "Unknown command ' '." or have some non-Null
command bound in player's RC file */ command bound in player's RC file */
if (bound_f != 0 && bound_f != &restonspace) if (bind && bind->cmd != &restonspace)
unrestonspace = bound_f; unrestonspace = bind->cmd;
gc.Cmd.commands[' '] = flags.rest_on_space ? &restonspace : unrestonspace; cmdbind_add(' ', flags.rest_on_space ? &restonspace : unrestonspace, FALSE);
} }
/* commands which accept 'm' prefix to request menu operation or other /* commands which accept 'm' prefix to request menu operation or other
@@ -3449,11 +3674,13 @@ rhack(int key)
const struct ext_func_tab *tlist; const struct ext_func_tab *tlist;
int res; int res;
gc.cmd_bind = cmdbind_get(key & 0xFF);
do_cmdq_extcmd: do_cmdq_extcmd:
if (cmdq_ec) if (cmdq_ec)
tlist = cmdq_ec; tlist = cmdq_ec;
else else
tlist = gc.Cmd.commands[key & 0xff]; tlist = gc.cmd_bind ? gc.cmd_bind->cmd : NULL;
/* current - use key to directly index cmdlist array */ /* current - use key to directly index cmdlist array */
if (tlist != 0) { if (tlist != 0) {
@@ -3477,7 +3704,8 @@ rhack(int key)
* the former call to help_dir() (for 'bad_command' below). * the former call to help_dir() (for 'bad_command' below).
*/ */
if (was_m_prefix) { if (was_m_prefix) {
pline("The %s command does not accept '%s' prefix.", custompline(SUPPRESS_HISTORY,
"The %s command does not accept '%s' prefix.",
tlist->ef_txt, which); tlist->ef_txt, which);
} else { } else {
uchar ch = tlist->key; uchar ch = tlist->key;
@@ -3614,7 +3842,7 @@ rhack(int key)
/* convert an x,y pair into a direction code */ /* convert an x,y pair into a direction code */
int int
xytod(coordxy x, coordxy y) xytodir(int x, int y)
{ {
int dd; int dd;
@@ -3626,7 +3854,7 @@ xytod(coordxy x, coordxy y)
/* convert a direction code into an x,y pair */ /* convert a direction code into an x,y pair */
void void
dtoxy(coord *cc, int dd) dirtocoord(coord *cc, int dd)
{ {
if (dd > DIR_ERR && dd < N_DIRS_Z) { if (dd > DIR_ERR && dd < N_DIRS_Z) {
cc->x = xdir[dd]; cc->x = xdir[dd];
@@ -3639,9 +3867,10 @@ int
movecmd(char sym, int mode) movecmd(char sym, int mode)
{ {
int d = DIR_ERR; int d = DIR_ERR;
struct Cmd_bind *bind = cmdbind_get(sym);
if (gc.Cmd.commands[(uchar) sym]) { if (bind && bind->cmd) {
int (*fnc)(void) = gc.Cmd.commands[(uchar) sym]->ef_funct; int (*fnc)(void) = bind->cmd->ef_funct;
if (mode == MV_ANY) { if (mode == MV_ANY) {
for (d = N_DIRS_Z - 1; d > DIR_ERR; d--) for (d = N_DIRS_Z - 1; d > DIR_ERR; d--)
@@ -3680,9 +3909,10 @@ boolean
redraw_cmd(char c) redraw_cmd(char c)
{ {
uchar uc = (uchar) c; uchar uc = (uchar) c;
const struct ext_func_tab *cmd = gc.Cmd.commands[uc]; struct Cmd_bind *bind = cmdbind_get(uc);
return (boolean) (cmd && cmd->ef_funct == doredraw); return (boolean) (bind && bind->cmd
&& bind->cmd->ef_funct == doredraw);
} }
/* /*
@@ -3732,7 +3962,7 @@ getdir(const char *s)
if (cmdq) { if (cmdq) {
if (cmdq->typ == CMDQ_DIR) { if (cmdq->typ == CMDQ_DIR) {
if (!cmdq->dirz) { if (!cmdq->dirz) {
dirsym = gc.Cmd.dirchars[xytod(cmdq->dirx, cmdq->diry)]; dirsym = gc.Cmd.dirchars[xytodir(cmdq->dirx, cmdq->diry)];
} else { } else {
dirsym = gc.Cmd.dirchars[(cmdq->dirz > 0) ? DIR_DOWN dirsym = gc.Cmd.dirchars[(cmdq->dirz > 0) ? DIR_DOWN
: DIR_UP]; : DIR_UP];
@@ -4500,7 +4730,7 @@ act_on_act(
cmdq_add_dir(CQ_CANNED, dx, dy, 0); cmdq_add_dir(CQ_CANNED, dx, dy, 0);
break; break;
case MCMD_MOVE_DIR: case MCMD_MOVE_DIR:
dir = xytod(dx, dy); dir = xytodir(dx, dy);
cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]); cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]);
break; break;
case MCMD_RIDE: case MCMD_RIDE:
@@ -4522,7 +4752,7 @@ act_on_act(
} }
break; break;
case MCMD_ATTACK_NEXT2U: case MCMD_ATTACK_NEXT2U:
dir = xytod(dx, dy); dir = xytodir(dx, dy);
cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]); cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]);
break; break;
case MCMD_TALK: case MCMD_TALK:
@@ -4632,7 +4862,7 @@ there_cmd_menu(coordxy x, coordxy y, int mod)
if (!K) { if (!K) {
/* no menu options, try to move */ /* no menu options, try to move */
if (next2u(x, y) && test_move(u.ux, u.uy, dx, dy, TEST_MOVE)) { if (next2u(x, y) && test_move(u.ux, u.uy, dx, dy, TEST_MOVE)) {
int dir = xytod(dx, dy); int dir = xytodir(dx, dy);
cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]); cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]);
} else if (flags.travelcmd) { } else if (flags.travelcmd) {
@@ -4726,7 +4956,7 @@ domouseaction(void)
/* directional commands */ /* directional commands */
dir = xytod(x, y); dir = xytodir(x, y);
if (!m_at(u.ux + x, u.uy + y) if (!m_at(u.ux + x, u.uy + y)
&& !test_move(u.ux, u.uy, x, y, TEST_MOVE)) { && !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) { if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
@@ -4765,7 +4995,7 @@ domouseaction(void)
cmdq_add_ec(CQ_CANNED, donull); cmdq_add_ec(CQ_CANNED, donull);
return ECMD_OK; return ECMD_OK;
} }
dir = xytod(x, y); dir = xytodir(x, y);
} }
/* move, attack, etc. */ /* move, attack, etc. */
@@ -4864,6 +5094,7 @@ staticfn int
parse(void) parse(void)
{ {
int foo; int foo;
struct Cmd_bind *bind;
iflags.in_parse = TRUE; iflags.in_parse = TRUE;
gc.command_count = 0; gc.command_count = 0;
@@ -4893,13 +5124,14 @@ parse(void)
gl.last_command_count = 0; gl.last_command_count = 0;
} else if (gi.in_doagain) { } else if (gi.in_doagain) {
gc.command_count = gl.last_command_count; gc.command_count = gl.last_command_count;
} else if (foo && gc.Cmd.commands[foo & 0xff] } else if (foo && (bind = cmdbind_get(foo & 0xFF)) != 0
/* these shouldn't go into the do-again buffer */ /* these shouldn't go into the do-again buffer */
&& (gc.Cmd.commands[foo & 0xff]->ef_funct == do_repeat && bind && bind->cmd
|| gc.Cmd.commands[foo & 0xff]->ef_funct == doprev_message && (bind->cmd->ef_funct == do_repeat
|| bind->cmd->ef_funct == doprev_message
/* this one might get put into the do-again buffer but /* this one might get put into the do-again buffer but
only if the interface code tells the core to do it */ only if the interface code tells the core to do it */
|| gc.Cmd.commands[foo & 0xff]->ef_funct == doextcmd)) { || bind->cmd->ef_funct == doextcmd)) {
/* gc.command_count will be set again when we /* gc.command_count will be set again when we
re-enter with gi.in_doagain set true */ re-enter with gi.in_doagain set true */
gc.command_count = gl.last_command_count; gc.command_count = gl.last_command_count;
@@ -5259,7 +5491,7 @@ yn_function(
query = qbuf; query = qbuf;
} }
if ((cmdq = cmdq_pop()) != 0) { if (addcmdq && (cmdq = cmdq_pop()) != 0) {
cq = *cmdq; cq = *cmdq;
free(cmdq); free(cmdq);
} else { } else {
@@ -5322,7 +5554,7 @@ yn_function(
it is most likely caused by saving a keystroke that was just used it is most likely caused by saving a keystroke that was just used
to answer a context-sensitive prompt, then using the do-again to answer a context-sensitive prompt, then using the do-again
command with context that has changed */ command with context that has changed */
if (resp && res && !strchr(resp, res)) { if (resp && *resp && res && !strchr(resp, res)) {
/* this probably needs refinement since caller is expecting something /* this probably needs refinement since caller is expecting something
within 'resp' and ESC won't be (it could be present, but as a flag within 'resp' and ESC won't be (it could be present, but as a flag
for unshown possibilities rather than as acceptable input) */ for unshown possibilities rather than as acceptable input) */
@@ -5404,9 +5636,11 @@ paranoid_ynq(
/* for empty input, return value c will already be 'n' */ /* for empty input, return value c will already be 'n' */
} while (ParanoidConfirm && strcmpi(ans, "no") && --trylimit); } while (ParanoidConfirm && strcmpi(ans, "no") && --trylimit);
} else if (accept_q) { } else if (accept_q) {
c = ynq(prompt); /* 'y', 'n', or 'q' */ /* 'y', 'n', or 'q' */
c = yn_function(prompt, ynqchars, 'n', FALSE);
} else { } else {
c = y_n(prompt); /* 'y' or 'n' */ /* 'y' or 'n' */
c = yn_function(prompt, ynchars, 'n', FALSE);
} }
if (c != 'y' && (c != 'q' || !accept_q)) if (c != 'y' && (c != 'q' || !accept_q))
c = 'n'; c = 'n';
+24 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 dbridge.c $NHDT-Date: 1702349063 2023/12/12 02:44:23 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.62 $ */ /* NetHack 3.7 dbridge.c $NHDT-Date: 1772771734 2026/03/05 20:35:34 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.70 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -399,7 +399,9 @@ e_survives_at(struct entity *etmp, coordxy x, coordxy y)
} }
staticfn void staticfn void
e_died(struct entity *etmp, int xkill_flags, int how) e_died(
struct entity *etmp,
int xkill_flags, int how)
{ {
if (is_u(etmp)) { if (is_u(etmp)) {
if (how == DROWNING) { if (how == DROWNING) {
@@ -444,6 +446,26 @@ e_died(struct entity *etmp, int xkill_flags, int how)
mk_message(xkill_flags), mk_corpse(xkill_flags)); mk_message(xkill_flags), mk_corpse(xkill_flags));
else /* you caused it */ else /* you caused it */
xkilled(etmp->emon, xkill_flags); xkilled(etmp->emon, xkill_flags);
/* if etmp gets life-saved, kill it again; otherwise we might end up
trying to place another monster (probably a xorn) on same spot */
if (!DEADMONSTER(etmp->emon)) {
int seeit = canspotmon(etmp->emon);
xkill_flags |= XKILL_NOMSG | XKILL_NOCONDUCT;
if (svc.context.mon_moving)
monkilled(etmp->emon, "", mk_corpse(xkill_flags));
else /* you caused it */
xkilled(etmp->emon, xkill_flags);
if (DEADMONSTER(etmp->emon)) {
if (seeit)
pline("Unfortunately for %s, %s is still crushed.",
mon_nam(etmp->emon), mhe(etmp->emon));
} else {
; /* FIXME: still not dead? What should we do now? */
}
}
etmp->edata = (struct permonst *) 0; etmp->edata = (struct permonst *) 0;
/* dead long worm handling */ /* dead long worm handling */
+7 -1
View File
@@ -247,6 +247,7 @@ static const struct instance_globals_c g_init_c = {
/* decl.c */ /* decl.c */
UNDEFINED_VALUES, /* chosen_windowtype */ UNDEFINED_VALUES, /* chosen_windowtype */
0, /* cmd_key */ 0, /* cmd_key */
NULL, /* cmd_bind */
0L, /* command_count */ 0L, /* command_count */
UNDEFINED_PTR, /* current_wand */ UNDEFINED_PTR, /* current_wand */
#ifdef DEF_PAGER #ifdef DEF_PAGER
@@ -413,6 +414,7 @@ static const struct instance_globals_i g_init_i = {
/* invent.c */ /* invent.c */
NULL, /* invbuf */ NULL, /* invbuf */
0U, /* invbufsize */ 0U, /* invbufsize */
FALSE, /* item_action_in_progress */
0, /* in_sync_perminvent */ 0, /* in_sync_perminvent */
/* mon.c */ /* mon.c */
NULL, /* itermonarr */ NULL, /* itermonarr */
@@ -590,7 +592,7 @@ static const struct instance_globals_o g_init_o = {
/* o_init.c */ /* o_init.c */
DUMMY, /* oclass_prob_totals */ DUMMY, /* oclass_prob_totals */
/* options.c */ /* options.c */
0, /* opt_phase */ phase_not_set, /* opt_phase */
FALSE, /* opt_initial */ FALSE, /* opt_initial */
FALSE, /* opt_from_file */ FALSE, /* opt_from_file */
FALSE, /* opt_need_redraw */ FALSE, /* opt_need_redraw */
@@ -673,6 +675,8 @@ static const struct instance_globals_r g_init_r = {
}; };
static const struct instance_globals_s g_init_s = { static const struct instance_globals_s g_init_s = {
/* allmain.c */
FALSE, /* saving_grace_turn */
/* artifact.c */ /* artifact.c */
0, /* spec_dbon_applies */ 0, /* spec_dbon_applies */
/* decl.c */ /* decl.c */
@@ -763,6 +767,8 @@ static const struct instance_globals_t g_init_t = {
}; };
static const struct instance_globals_u g_init_u = { static const struct instance_globals_u g_init_u = {
/* allmain.c */
0, /* uhp_at_start_of_monster_turn */
/* botl.c */ /* botl.c */
FALSE, /* update_all */ FALSE, /* update_all */
/* decl.c */ /* decl.c */
+17 -11
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 detect.c $NHDT-Date: 1745114235 2025/04/19 17:57:15 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.190 $ */ /* NetHack 3.7 detect.c $NHDT-Date: 1763708572 2025/11/20 23:02:52 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.191 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2018. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -26,7 +26,7 @@ staticfn void reconstrain_map(void);
staticfn void map_redisplay(void); staticfn void map_redisplay(void);
staticfn void browse_map(unsigned, const char *); staticfn void browse_map(unsigned, const char *);
staticfn void map_monst(struct monst *, boolean); staticfn void map_monst(struct monst *, boolean);
staticfn void do_dknown_of(struct obj *); staticfn void observe_recursively(struct obj *);
staticfn boolean check_map_spot(coordxy, coordxy, char, unsigned); staticfn boolean check_map_spot(coordxy, coordxy, char, unsigned);
staticfn boolean clear_stale_map(char, unsigned); staticfn boolean clear_stale_map(char, unsigned);
staticfn void sense_trap(struct trap *, coordxy, coordxy, int); staticfn void sense_trap(struct trap *, coordxy, coordxy, int);
@@ -246,14 +246,14 @@ o_material(struct obj *obj, unsigned material)
} }
staticfn void staticfn void
do_dknown_of(struct obj *obj) observe_recursively(struct obj *obj)
{ {
struct obj *otmp; struct obj *otmp;
obj->dknown = 1; observe_object(obj);
if (Has_contents(obj)) { if (Has_contents(obj)) {
for (otmp = obj->cobj; otmp; otmp = otmp->nobj) for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
do_dknown_of(otmp); observe_recursively(otmp);
} }
} }
@@ -638,7 +638,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
if (do_dknown) if (do_dknown)
for (obj = gi.invent; obj; obj = obj->nobj) for (obj = gi.invent; obj; obj = obj->nobj)
do_dknown_of(obj); observe_recursively(obj);
for (obj = fobj; obj; obj = obj->nobj) { for (obj = fobj; obj; obj = obj->nobj) {
if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) { if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) {
@@ -648,7 +648,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
ct++; ct++;
} }
if (do_dknown) if (do_dknown)
do_dknown_of(obj); observe_recursively(obj);
} }
for (obj = svl.level.buriedobjlist; obj; obj = obj->nobj) { for (obj = svl.level.buriedobjlist; obj; obj = obj->nobj) {
@@ -659,7 +659,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
ct++; ct++;
} }
if (do_dknown) if (do_dknown)
do_dknown_of(obj); observe_recursively(obj);
} }
if (u.usteed) if (u.usteed)
@@ -673,7 +673,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
|| o_in(obj, boulder)) || o_in(obj, boulder))
ct++; ct++;
if (do_dknown) if (do_dknown)
do_dknown_of(obj); observe_recursively(obj);
} }
if ((is_cursed && M_AP_TYPE(mtmp) == M_AP_OBJECT if ((is_cursed && M_AP_TYPE(mtmp) == M_AP_OBJECT
&& (!class || class == objects[mtmp->mappearance].oc_class)) && (!class || class == objects[mtmp->mappearance].oc_class))
@@ -932,7 +932,7 @@ detect_obj_traps(
} }
if (Is_box(otmp) && otmp->otrapped) { if (Is_box(otmp) && otmp->otrapped) {
otmp->tknown = 1; otmp->tknown = 1;
otmp->dknown = 1; observe_object(otmp);
result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE; result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE;
if (ft) { if (ft) {
flash_glyph_at(x, y, trapglyph, FOUND_FLASH_COUNT); flash_glyph_at(x, y, trapglyph, FOUND_FLASH_COUNT);
@@ -1508,7 +1508,7 @@ do_vicinity_map(
unlike object detection, we don't notice buried items */ unlike object detection, we don't notice buried items */
otmp = svl.level.objects[zx][zy]; otmp = svl.level.objects[zx][zy];
if (extended) if (extended)
otmp->dknown = 1; observe_object(otmp);
map_object(otmp, TRUE); map_object(otmp, TRUE);
newglyph = glyph_at(zx, zy); newglyph = glyph_at(zx, zy);
/* if otmp is underwater, we'll need to redisplay the water */ /* if otmp is underwater, we'll need to redisplay the water */
@@ -2179,6 +2179,12 @@ reveal_terrain_getglyph(
keep_mons = (which_subset & TER_MON) != 0, keep_mons = (which_subset & TER_MON) != 0,
full = (which_subset & TER_FULL) != 0; full = (which_subset & TER_FULL) != 0;
/*
* FIXME:
* travel treats discovered vibrating square as if it were terrain
* rather than a trap so this should do so too.
*/
/* for 'full', show the actual terrain for the entire level, /* for 'full', show the actual terrain for the entire level,
otherwise what the hero remembers for seen locations with otherwise what the hero remembers for seen locations with
monsters, objects, and/or traps removed as caller dictates */ monsters, objects, and/or traps removed as caller dictates */
+2 -2
View File
@@ -1256,7 +1256,7 @@ use_pick_axe2(struct obj *obj)
&& (trap_with_u = t_at(u.ux, u.uy)) && (trap_with_u = t_at(u.ux, u.uy))
&& is_pit(trap->ttyp) && is_pit(trap->ttyp)
&& !conjoined_pits(trap, trap_with_u, FALSE)) { && !conjoined_pits(trap, trap_with_u, FALSE)) {
int idx = xytod(u.dx, u.dy); int idx = xytodir(u.dx, u.dy);
if (idx != DIR_ERR) { if (idx != DIR_ERR) {
int adjidx = DIR_180(idx); int adjidx = DIR_180(idx);
@@ -1617,7 +1617,7 @@ zap_dig(void)
if (u.utrap && u.utraptype == TT_PIT if (u.utrap && u.utraptype == TT_PIT
&& (trap_with_u = t_at(u.ux, u.uy))) { && (trap_with_u = t_at(u.ux, u.uy))) {
pitdig = TRUE; pitdig = TRUE;
diridx = xytod(u.dx, u.dy); diridx = xytodir(u.dx, u.dy);
} }
digdepth = rn1(18, 8); digdepth = rn1(18, 8);
tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam)); tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam));
+3 -3
View File
@@ -346,7 +346,7 @@ map_object(struct obj *obj, int show)
neardist = (r * r) * 2 - r; /* same as r*r + r*(r-1) */ neardist = (r * r) * 2 - r; /* same as r*r + r*(r-1) */
if (distu(x, y) <= neardist) { if (distu(x, y) <= neardist) {
obj->dknown = 1; observe_object(obj);
glyph = obj_to_glyph(obj, newsym_rn2); glyph = obj_to_glyph(obj, newsym_rn2);
} }
} }
@@ -1585,7 +1585,7 @@ see_nearby_objects(void)
if (!cansee(ix, iy) || distu(ix, iy) > neardist) if (!cansee(ix, iy) || distu(ix, iy) > neardist)
continue; continue;
obj->dknown = 1; /* near enough to see it */ observe_object(obj);
/* operate on remembered glyph rather than current one */ /* operate on remembered glyph rather than current one */
glyph = levl[ix][iy].glyph; glyph = levl[ix][iy].glyph;
if (glyph_is_generic_object(glyph)) if (glyph_is_generic_object(glyph))
@@ -2656,7 +2656,7 @@ const int altarcolors[] = {
altar_color_unaligned, altar_color_chaotic, altar_color_neutral, altar_color_unaligned, altar_color_chaotic, altar_color_neutral,
altar_color_lawful, altar_color_other altar_color_lawful, altar_color_other
}; };
const int explodecolors[7] = { const int explodecolors[EXPL_MAX] = {
explode_color_dark, explode_color_noxious, explode_color_muddy, explode_color_dark, explode_color_noxious, explode_color_muddy,
explode_color_wet, explode_color_magical, explode_color_fiery, explode_color_wet, explode_color_magical, explode_color_fiery,
explode_color_frosty, explode_color_frosty,
+18 -7
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 do.c $NHDT-Date: 1737287889 2025/01/19 03:58:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.399 $ */ /* NetHack 3.7 do.c $NHDT-Date: 1774269965 2026/03/23 04:46:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.404 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -839,7 +839,7 @@ dropz(struct obj *obj, boolean with_impact)
map_object(obj, 0); map_object(obj, 0);
newsym(u.ux, u.uy); /* remap location under self */ newsym(u.ux, u.uy); /* remap location under self */
} }
(void) encumber_msg(); encumber_msg();
} }
/* when swallowed, move dropped object from OBJ_FREE to u.ustuck's inventory; /* when swallowed, move dropped object from OBJ_FREE to u.ustuck's inventory;
@@ -1942,8 +1942,18 @@ goto_level(
if (new) { if (new) {
char dloc[QBUFSZ]; char dloc[QBUFSZ];
/* Astral is excluded as a major event here because entry to it /* Astral is excluded as a major event here because entry to it
is already one due to that being an achievement */ is already one such due to that being an achievement;
boolean major = In_endgame(&u.uz) && !Is_astralevel(&u.uz); for the quest, listing the start, locate, and goal levels would
seem reasonable but all quest levels are included for simplicity--
level 2 (or 3 if hero level teleports after obtaining permission
to enter) is useful to show since it indicates that hero has
actually entered the quest rather than just received permission
to do so, and listing the goal level could be used to figure out
whether level 5 is the end or there's another level (ESP reveals
the same thing, but is part of normal game play as opposed to
#chronicle leaking information that hero hasn't discovered yet) */
boolean major = ((In_endgame(&u.uz) && !Is_astralevel(&u.uz))
|| In_quest(&u.uz));
(void) describe_level(dloc, 2); (void) describe_level(dloc, 2);
livelog_printf(major ? LL_ACHIEVE : LL_DEBUG, "entered %s", dloc); livelog_printf(major ? LL_ACHIEVE : LL_DEBUG, "entered %s", dloc);
@@ -2248,7 +2258,8 @@ revive_mon(anything *arg, long timeout UNUSED)
/* corpse will revive somewhere else if there is a monster in the way; /* corpse will revive somewhere else if there is a monster in the way;
Riders get a chance to try to bump the obstacle out of their way */ Riders get a chance to try to bump the obstacle out of their way */
if (is_displacer(mptr) && body->where == OBJ_FLOOR if (is_displacer(mptr) && body->where == OBJ_FLOOR
&& get_obj_location(body, &x, &y, 0) && (mtmp = m_at(x, y)) != 0) { && get_obj_location(body, &x, &y, 0) && (mtmp = m_at(x, y)) != 0 &&
svl.level.flags.stasis_until < svm.moves) {
boolean notice_it = canseemon(mtmp); /* before rloc() */ boolean notice_it = canseemon(mtmp); /* before rloc() */
char *monname = Monnam(mtmp); char *monname = Monnam(mtmp);
@@ -2431,7 +2442,7 @@ set_wounded_legs(long side, int timex)
direct assignment instead of bitwise-OR so getting wounded in direct assignment instead of bitwise-OR so getting wounded in
one leg mysteriously healed the other */ one leg mysteriously healed the other */
EWounded_legs |= side; EWounded_legs |= side;
(void) encumber_msg(); encumber_msg();
} }
void void
@@ -2470,7 +2481,7 @@ heal_legs(
more when steed becomes healthy, then possible floor more when steed becomes healthy, then possible floor
feedback, then able to carry less when back on foot]. */ feedback, then able to carry less when back on foot]. */
if (how == 0) if (how == 0)
(void) encumber_msg(); encumber_msg();
} }
} }

Some files were not shown because too many files have changed in this diff Show More