diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 8755374426..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,117 +0,0 @@
-language: c
-matrix:
- include:
- - os: linux
- env: DESCR=linux-xenial-gcc HINTS=linux
- compiler: gcc
- script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make install"
- - os: linux
- env: DESCR=linux-xenial-clang HINTS=linux
- compiler: clang
- script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make install"
- - os: linux
- env: DESCR=linux-xenial-gcc-x11 HINTS=linux-x11
- compiler: gcc
- addons:
- apt:
- packages:
- - libx11-dev
- - libxaw7-dev
- - xfonts-utils
- script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make install"
- - os: linux
- env: DESCR=linux-xenial-gcc-qt5 HINTS=linux-qt5
- compiler: gcc
- addons:
- apt:
- packages:
- - libx11-dev
- - libxaw7-dev
- - xfonts-utils
- - qtbase5-dev
- - qtmultimedia5-dev
- - qtbase5-dev-tools
- script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && QT_SELECT=5 make MOC=moc install"
- - os: linux
- env: DESCR=linux-bionic-gcc-x11 HINTS=linux-x11
- dist: bionic
- compiler: gcc
- addons:
- apt:
- packages:
- - libx11-dev
- - libxaw7-dev
- - xfonts-utils
- script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make install"
- - os: linux
- env: DESCR=linux-xenial-gcc-minimal HINTS=linux-minimal
- compiler: gcc
- script: |
- cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../
- sed -i '/^#define CLIPPING/d' include/config.h
- sed -i '/^#define COMPRESS/d' include/config.h
- #sed -i '/^#define DOAGAIN/d' include/config.h
- sed -i '/^#define DUMPLOG/d' include/config.h
- #sed -i '/^#define GDBPATH/d' include/config.h
- #sed -i '/^#define GREPPATH/d' include/config.h
- sed -i '/^#define INSURANCE/d' include/config.h
- sed -i '/^#define LOGFILE/d' include/config.h
- sed -i '/^#define NEWS/d' include/config.h
- sed -i '/^#define PANICLOG/d' include/config.h
- #sed -i '/^#define STATUS_HILITES/d' include/config.h
- sed -i '/^#define SYSCF/d' include/config.h
- sed -i '/^#define USER_SOUNDS/d' include/config.h
- sed -i '/^#define XLOGFILE/d' include/config.h
-
- sed -i '/^#define MAIL/d' include/unixconf.h
- sed -i '/^#define SHELL/d' include/unixconf.h
- sed -i '/^#define SUSPEND/d' include/unixconf.h
- sed -i 's/^#define TEXTCOLOR//' include/unixconf.h
- make install
- cat dat/options
- - os: windows
- env: DESCR=windows-visualstudio
- language: shell
- script:
- - ./win/win32/vs2017/travisci.sh
- - os: windows
-# install: choco install mingw
- env: DESCR=windows-mingw
- script:
- - git clone --depth 1 https://github.com/wmcbrine/PDCurses.git ../pdcurses
- - export ADD_CURSES=Y
- - export PDCURSES_TOP=../../pdcurses
- - cd src
- - cp ../sys/winnt/Makefile.gcc ./Makefile
- - mingw32-make install
- exclude:
-# - os: osx
-# osx_image: xcode10.3
-# env: DESCR=osx-xcode10.3-x11 HINTS=macosx10.14 WANT_WIN_CURSES=1 WANT_WIN_X11=1 USE_XPM=1
-# compiler: clang
-# script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make install"
- - os: osx
- osx_image: xcode10.2
- env: HINTS=macosx10.14
- compiler: clang
- script: "cd sys/unix/ && sh setup.sh hints/$HINTS && cd ../../ && make install"
-#
-sudo: false
-notifications:
- email:
- recipients:
- - devteam@nethack.org
-#
-deploy:
- provider: releases
- api_key:
- secure: "U0Dt2CXrcG8Yi4taUCT/6AnM+0IJtdCv6IVG/2rGooUY3pZjNWE9XDM6X9ZeAmbI79aN6FPTppjUf3KbB/upYeJt+8mrjnxEk/ZTO1xXDDW8iL/DiqnczoFsMGmPsTM+Fkeak8bu0SifI7Qkx9i1N+zOyl2VdlaxGjchPfl/OJw2jcQs7rOGRfr23/rapZKTcFq+BFlxMiIHa0dXbCJ9vagdlyAeclOCtPjw1VoH/Cb/+0/Xlx2MFPncw4/1P+bO/fPantHyehh3/WCDVCnI4M7ftONpsTVRrQ+Hml89teUH9/1xXUOpbCeVghWr1rumLcQzMqLKNj2lP/gm9co2/DKpxiUPUzBfO/9Jvl1CNoEwPYQBRNb38kggDvAT4vKX38Oi5sZvumFEO4L0y7o4cW6SA4/CYIykfxOdkrryt8ltfWwopdy3I/DothYw31vJ9GsZOCAShFRAy3hJxYUbHhT+7SDUBadVSEkb4UqxQ+7zntAVT+Lp4DXLAfvsWxZGrQoP/IrWAgNOLRKILubpzh+YpadMH3Ygha2JRAeJAEZ3DnXf3vOOAucWnk4mNXDbW35GTDTAJDWMvddZCfsrUI/uHxgaRjFs9fLX1X5tqhGnsr27sKLWyX+zrIPVV0TPl3AzYPAf6Bc8Okeu+JEGQERvvgSasCuYcmhgYznBVJI="
- file_glob: true
- file:
- - "$TRAVIS_TAG.x86.zip"
- skip_cleanup: true
- on:
- tags: true
- prerelease: false
- name: "Release build of NetHack 3.6.6"
- body: "This is an auto generated Release build of NetHack 3.6.6"
diff --git a/Files b/Files
index 6208fb4758..26e96b81b6 100644
--- a/Files
+++ b/Files
@@ -7,7 +7,7 @@ from or not transferred to your system if you wish.
.:
(files in top directory)
-.clang-format .travis.yml Files Porting README
+.clang-format Files Porting README
DEVEL:
(files for people developing changes to NetHack)
@@ -42,18 +42,22 @@ tower.des tribute wizhelp yendor.des
doc:
(files for all versions)
-Guidebook.mn Guidebook.tex Guidebook.txt config.nh dgn_comp.6
-dgn_comp.txt dlb.6 dlb.txt fixes10.0 fixes14.f
-fixes22.0 fixes23.e fixes30.0 fixes30.pl01 fixes30.pl02
-fixes30.pl03 fixes30.pl04 fixes30.pl05 fixes30.pl06 fixes30.pl07
-fixes30.pl08 fixes30.pl09 fixes30.pl10 fixes31.1 fixes31.2
-fixes31.3 fixes32.0 fixes32.1 fixes32.2 fixes32.3
-fixes33.0 fixes33.1 fixes34.0 fixes34.1 fixes34.2
-fixes34.3 fixes35.0 fixes36.0 fixes36.1 fixes36.2
-fixes36.3 fixes36.4 fixes36.5 fixes36.6 lev_comp.6
-lev_comp.txt makedefs.6 makedefs.txt mn.7 mn.txt
-mnh.7 mnh.txt nethack.6 nethack.txt recover.6
-recover.txt tmac.n tmac.nh window.doc
+Gbk-1pg-pfx.mn Gbk-1pg-sfx.mn Guidebook.mn Guidebook.tex
+Guidebook.txt config.nh dgn_comp.6 dgn_comp.txt
+dlb.6 dlb.txt fixes10.0 fixes14.f
+fixes22.0 fixes23.e fixes30.0 fixes30.pl01
+fixes30.pl02 fixes30.pl03 fixes30.pl04 fixes30.pl05
+fixes30.pl06 fixes30.pl07 fixes30.pl08 fixes30.pl09
+fixes30.pl10 fixes31.1 fixes31.2 fixes31.3
+fixes32.0 fixes32.1 fixes32.2 fixes32.3
+fixes33.0 fixes33.1 fixes34.0 fixes34.1
+fixes34.2 fixes34.3 fixes35.0 fixes36.0
+fixes36.1 fixes36.2 fixes36.3 fixes36.4
+fixes36.5 fixes36.6 lev_comp.6 lev_comp.txt
+makedefs.6 makedefs.txt mn.7 mn.txt
+mnh.7 mnh.txt nethack.6 nethack.txt
+recover.6 recover.txt tmac.n tmac.nh
+window.doc
include:
(files for GEM versions)
@@ -278,8 +282,7 @@ sys/winnt:
(files for Windows 7/8.x/10 version)
.nethackrc.template Install.nt Makefile.gcc
Makefile.msc console.rc nethack.def
-nh340key.c nhdefkey.c nhico.uu
-nhraykey.c nhsetup.bat ntsound.c
+nhico.uu nhsetup.bat ntsound.c
nttty.c porthelp stub-pdcscrn.c
stubs.c sysconf.template win10.c
win10.h win32api.h windmain.c
@@ -288,7 +291,7 @@ winnt.c winos.h
util:
(files for all versions)
dgn_main.c dlb_main.c lev_main.c makedefs.c mdgrep.h mdgrep.pl
-panic.c recover.c
+panic.c recover.c stripbs.c
(lex/yacc input for special level and dungeon compilers)
dgn_comp.l dgn_comp.y lev_comp.l lev_comp.y
@@ -399,9 +402,6 @@ default_lib.props dgncomp.vcxproj
dirs.props dlb.vcxproj
dll.props files.props
levcomp.vcxproj makedefs.vcxproj
-nh340key.def nh340key.vcxproj
-nhdefkey.def nhdefkey.vcxproj
-nhraykey.def nhraykey.vcxproj
recover.vcxproj tile2bmp.vcxproj
tilemap.vcxproj tiles.vcxproj
travisci.sh uudecode.vcxproj
diff --git a/README b/README
index 3b4ebacb79..87044cf99c 100644
--- a/README
+++ b/README
@@ -1,14 +1,14 @@
- NetHack 3.6.6 -- General information March 2020
+ NetHack 3.6.7 -- General information February 2023
NetHack 3.6 is an enhancement to the dungeon exploration game NetHack,
which is a distant descendent of Rogue and Hack, and a direct descendent of
NetHack 3.4 as there was no NetHack 3.5 release.
-NetHack 3.6.6 is the official release of NetHack that follows NetHack 3.6.5
-and contains bug fixes since 3.6.5, including a security fix that affected
-versions 3.6.1, 3.6.2, 3.6.3, 3.6.4 and 3.6.5.
+NetHack 3.6.7 is the official release of NetHack that follows NetHack 3.6.6
+and contains bug fixes since 3.6.6, including a security fix which prompted
+the release.
-The file doc/fixes36.6 in the source distribution has a full list of fixes.
+The file doc/fixes36.7 in the source distribution has a full list of fixes.
The text in there was written for the development team's own use and is
provided "as is", so please do not ask us to further explain the entries in
that file. Some entries might be considered "spoilers", particularly in the
@@ -17,12 +17,28 @@ that file. Some entries might be considered "spoilers", particularly in the
Below you will find some other general notes that were not considered
spoilers:
- * invalid status highlight color could be maliciously used to corrupt memory
- * formatting corpse names used internal buffers differently from formatting
- * other objects and could potentially clobber memory
- * avoid divide by 0 crash if 'bogusmon' (file of bogus monster types) is empty
- * avoid #wizrumorcheck crash if either 'rumors.tru' or 'rumors.fal' or both
- * were empty when makedefs built 'rumors'
+ * during engraving, spaces were counted instead of non-space (cherry-pick of
+ 4e0a1e04 from NetHack-3.7)
+ * avoid potential buffer overflow in append_str()
+ * resolve missing dependency in NetHack.sln
+ * code in include/tradstdc.h was trying to suppress warn_unused result by
+ defining warn_unused_result to an empty string and that began causing
+ a build error within a system-supplied header file cdefs.h when using
+ ubuntu impish 21.10; disable that for any Linux unless GCC_URWARN is
+ defined to force it back into effect
+ * update_inventory() after leash goes slack
+ * player assigned name for monsters, specific objects, or object types could be
+ longer than what was intented to be allowed; for 'curses', much longer
+ * windows: added winflexbison to travis-ci configuration to permit full build of
+ levcomp and dgncomp
+ * windows: a bad chdir specified in win/win32/dgnstuff.mak caused full build to
+ abort
+ * windows: the console.rc file had outdated information stating 3.6.3 when the
+ official 3.6.6 binary was built.
+ * windows: switch from using keyhandling dll's to incorporating the three
+ variations (default, ray, 340) in sys/winnt/nttty.c
+ * curses: cherry-picked selectsaved code from 3.7 for menu of save files
+ * NetHackW: fix delay rendering of cursor when using farlook
- - - - - - - - - - -
@@ -170,6 +186,6 @@ In our own patches, we will assume that your code is synchronized with ours.
-- Good luck, and happy Hacking --
-# $NHDT-Date: 1583508658 2020/03/06 15:30:58 $ $NHDT-Branch: NetHack-3.6-Mar2020 $:$NHDT-Revision: 1.80 $
+# $NHDT-Date: 1672610729 2023/01/01 22:05:29 $ $NHDT-Branch: releasebits-3.6 $:$NHDT-Revision: 1.81 $
# Copyright (c) 2012 by Michael Allison
# NetHack may be freely redistributed. See license for details.
diff --git a/dat/.gitignore b/dat/.gitignore
index 748a8ffe17..506e251a9f 100644
--- a/dat/.gitignore
+++ b/dat/.gitignore
@@ -9,6 +9,7 @@ rumors
bogusmon
engrave
epitaph
+grep*.tmp
x11tiles
nhtiles.bmp
*.lev
diff --git a/dat/hh b/dat/hh
index 75f87b33b7..cd6386dffd 100644
--- a/dat/hh
+++ b/dat/hh
@@ -9,9 +9,9 @@ b j n 1 2 3 g
: run in direction until something
case means the Control key, not a caret)
> down m: move without picking up objects/fighting
F: fight even if you don't sense a monster
- If the number_pad option is set, the number keys move instead.
- Depending on the platform, Shift number (on the numberpad),
- Meta number, or Alt number will invoke the YUHJKLBN commands.
+ If the number_pad option is set, the digit keys move instead.
+ Depending on the platform, Shift digit (on the numberpad),
+ Meta digit, or Alt digit will invoke the YUHJKLBN commands.
Control may or may not work when number_pad is enabled,
depending on the platform's capabilities.
Digit '5' acts as 'G' prefix, unless number_pad is set to 2
@@ -22,111 +22,135 @@ b j n 1 2 3 g: run in direction until something
used but 'y' and 'z' are swapped.
General commands:
-? help display one of several informative texts
-#quit quit end the game without saving current game
-S save save the game (to be continued later) and exit
- [to restore, play again and use the same character name]
-! sh escape to some SHELL (if allowed; 'exit' to resume play)
-^Z suspend suspend the game (independent of your current suspend char)
+? help display one of several informative texts
+#quit quit end the game without saving current game
+S save save the game (to be continued later) and exit
+ [to restore, play again and use the same character name;
+ use #quit to quit without saving]
+! sh escape to some SHELL (if allowed; 'exit' to resume play)
+^Z suspend suspend the game (independent of your current suspend char)
[on UNIX(tm)-based systems, use the 'fg' command to resume]
-O options set options
-/ what-is tell what a map symbol represents
-\ known display list of what's been discovered
-v version display version number
-V history display game history
-^A again redo the previous command (^A denotes the keystroke CTRL-A)
-^R redraw redraw the screen
-^P prevmsg repeat previous message (subsequent ^P's repeat earlier ones)
+O options set options
+/ what-is tell what a map symbol represents
+\ known display list of what's been discovered
+v version display version number
+V history display game history
+^A again redo the previous command
+^R redraw redraw the screen
+^P prevmsg repeat previous message (consecutive ^P's repeat earlier ones)
# introduces an extended command (#? for a list of them)
-& what-does describe the command a keystroke invokes
+& what-does describe the command a keystroke invokes
+
+Control characters are depicted as '^' followed by a letter. Depress Ctrl
+or Control like a shift key then type the letter. Control characters are
+case-insensitive; ^D is the same as ^d, Ctrl+d is same as Ctrl+Shift+d.
+There are a few non-letter control characters; nethack uses ^[ as a synonym
+for Escape (or vice versa) but none of the others.
Game commands:
-^D kick kick (a door, or something else)
-^T 'port teleport (if you can)
-^X show show your attributes
-a apply apply or use a tool (pick-axe, key, camera, etc.)
-A armor take off all armor
-c close close a door
-C call name a monster, an individual object, or a type of object
-d drop drop an object. d7a: drop seven items of object 'a'
-D Drop drop selected types of objects
-e eat eat something
-E engrave write a message in the dust on the floor (E- use fingers)
-f fire fire ammunition from quiver
-F fight followed by direction, fight a monster
-i invent list your inventory (all objects you are carrying)
-I Invent list selected parts of your inventory
- Iu: list unpaid objects
- Ix: list unpaid but used up items
- I$: count your money
-o open open a door
-p pay pay your bill (in a shop)
-P puton put on an accessory (ring, amulet, etc)
-q quaff drink something (potion, water, etc)
-Q quiver select ammunition for quiver (use '#quit' to quit)
-r read read a scroll or spellbook
-R remove remove an accessory (ring, amulet, etc)
-s search search for secret doors, hidden traps and monsters
-t throw throw or shoot a weapon
-T takeoff take off some armor
-w wield wield a weapon (w- wield nothing)
-W wear put on some armor
-x xchange swap wielded and secondary weapons
-X twoweapon toggle two-weapon combat (use '#explore' for explore mode)
-z zap zap a wand (use y instead of z if number_pad is -1)
-Z Zap cast a spell (use Y instead of Z if number_pad is -1)
-< up go up the stairs
-> down go down the stairs
-^ trap_id identify a previously found trap
-),[,=,",( ask for current items of specified symbol in use
-* ask for combination of ),[,=,",( all at once
-$ gold count your gold
-+ spells list the spells you know; also rearrange them if desired
-` classkn display known items for one class of objects
-_ travel move via a shortest-path algorithm to a point on the map
-. rest wait a moment
-, pickup pick up all you can carry
+^D kick kick (a door, or something else)
+^T Tport teleport (if you can)
+^X show show your attributes
+a apply apply or use a tool (pick-axe, key, camera, etc.)
+A takeoffall choose multiple items of armor, accessories, and weapons
+ to take off, remove, unwield (uses same amount of game time
+ as removing them individually with T,R,w- would take)
+c close close a door
+C call name a monster, an individual object, or a type of object
+d drop drop an object. d7a: drop seven items of object 'a'
+D Drop drop selected types of objects
+e eat eat something
+E engrave write a message in the dust on the floor (E- use fingers)
+f fire fire ammunition from quiver
+F fight followed by direction, fight a monster
+i invent list your inventory (all objects you are carrying)
+I Invent list selected parts of your inventory; for example
+ I( list all tools, or I" list all amulets
+ IB list all items known to be blessed
+ IU uncursed, or IC cursed, or IX unknown bless state
+ Iu when in a shop, list unpaid objects being carried
+ Ix in a shop, list any fees and used-up shop-owned items
+o open open a door
+p pay pay your bill (in a shop)
+P puton put on an accessory (ring, amulet, etc; can be used to wear
+ armor too, but armor items aren't listed as likely candidates)
+q quaff drink something (potion, water, etc)
+Q quiver select ammunition for quiver (use '#quit' to quit)
+r read read a scroll or spellbook
+R remove remove an accessory (ring, amulet, etc; can be used to take
+ off armor too)
+s search search for secret doors, hidden traps and monsters
+t throw throw or shoot a weapon
+T takeoff take off some armor; can be used to remove accessories too,
+ but those aren't listed as likely candidates)
+w wield wield a weapon (w- wield nothing to unwield current weapon)
+W wear wear an item of armor; can be used to put on accessories too,
+ but those aren't listed as likely candidates)
+x xchange swap wielded and secondary weapons
+X twoweapon toggle two-weapon combat if role allows that
+z zap zap a wand (use y instead of z if number_pad is -1)
+Z Zap cast a spell (use Y instead of Z if number_pad is -1)
+< up go up the stairs
+> down go down the stairs
+^ trap_id identify a previously found trap
+),[,=,",( show current items of specified symbol in use
+* show combination of ),[,=,",( all at once
+$ gold count your gold
++ spells list the spells you know; also rearrange them if desired
+` classkn display known items for one class of objects
+_ travel move via a shortest-path algorithm to a point on the map
+. rest wait a moment
+, pickup pick up all you can carry
@ toggle "pickup" (auto pickup) option on and off
-: look look at what is here
-; farlook look at what is somewhere else by selecting a map symbol
+: look look at what is here
+; farlook look at what is somewhere else by selecting a map location
+ (for a monster on top of one or more objects, only describes
+ that monster; for a pile of objects, only describes top one)
-Keyboards that have a meta key can also use these extended commands
-via the meta modifier instead of the # prefix:
+Keyboards that have a meta key (some use Alt for that, so typing Alt as a
+shift plus 'e' would generate 'M-e') can also use these extended commands
+via the meta modifier as an alternative to using the # prefix. Unlike
+control characters, meta characters are case-sensitive so M-a is different
+from M-A. Type the latter with two keys used as shifts, Meta+Shift+a.
M-? display extended command help (if the platform allows this)
-M-2 twoweapon toggle two-weapon combat (unless number_pad is enabled)
-M-a adjust adjust inventory letters
-M-A annotate add a one-line note to the current dungeon level (see M-O)
-M-c chat talk to someone
-M-C conduct view optional challenges
-M-d dip dip an object into something
-M-e enhance advance or check weapon and spell skills
-M-f force force a lock
-M-i invoke invoke an object's special powers
-M-j jump jump to another location
-M-l loot loot a box on the floor
-M-m monster use a monster's special ability
-M-n name name a monster, an individual object, or a type of object
-M-N name synonym for M-n
-M-o offer offer a sacrifice to the gods
-M-O overview display information about visited levels and annotations
-M-p pray pray to the gods for help
-M-q quit stop playing
-M-r rub rub a lamp or a stone
-M-R ride mount or dismount saddled steed
-M-s sit sit down
-M-t turn turn undead
-M-T tip upend a container to dump out its contents
-M-u untrap untrap something
-M-v version print compile time options for this version
-M-w wipe wipe off your face
+M-2 twoweapon toggle two-weapon combat (unless number_pad is enabled)
+M-a adjust adjust inventory letters
+M-A annotate add a one-line note to the current dungeon level (see M-O)
+M-c chat talk to someone
+M-C conduct view optional challenges
+M-d dip dip an object into something
+M-e enhance show weapon and spell skills, can improve them if eligible
+M-f force force a lock
+M-i invoke invoke an object's special powers
+M-j jump jump to another location
+M-l loot loot a box on the floor
+M-m monster when polymorphed, use monster's special ability
+M-n name name a monster, an individual object, or a type of object
+M-N name synonym for M-n (both are the same as C)
+M-o offer offer a sacrifice to the gods
+M-O overview display information about visited levels and annotations
+M-p pray pray to the gods for help
+M-q quit stop playing without saving game (use S to save and exit)
+M-r rub rub a lamp or a stone
+M-R ride mount or dismount saddled steed
+M-s sit sit down
+M-t turn turn undead if role allows that
+M-T tip upend a container to dump out its contents
+M-u untrap untrap something
+M-v version print compile time options for this version
+M-w wipe wipe off your face
+M-X explore switch from regular play to non-scoring explore mode
-If the "number_pad" option is on, these additional variants are available:
+If the 'number_pad' option is on, keys usually used for movement can be
+used for various commands:
n followed by number of times to repeat the next command
-h help display one of several informative texts, like '?'
-j jump jump to another location
-k kick kick something (usually a door)
-l loot loot a box on the floor
-N name name an item or type of object
-u untrap untrap something (usually a trapped object)
+h help display one of several informative texts, like '?'
+j jump jump to another location
+k kick kick something (usually a door)
+l loot loot a box on the floor
+N name name an item or type of object
+u untrap untrap something (usually a trapped object)
+
+Additional commands are available in debug mode (also known as wizard mode).
diff --git a/dat/history b/dat/history
index 2d76fc5ce1..2d318f6190 100644
--- a/dat/history
+++ b/dat/history
@@ -232,6 +232,9 @@ and a small number of bug fixes.
NetHack 3.6.6 was released on March 8, 2020 containing a security fix and
some bug fixes.
+NetHack 3.6.7 was released in February 2023 containing a security fix and
+some bug fixes.
+
The official NetHack web site is maintained by Ken Lorber at
http://www.nethack.org/.
diff --git a/doc/.gitattributes b/doc/.gitattributes
index 80fecb1d5d..748efbe699 100644
--- a/doc/.gitattributes
+++ b/doc/.gitattributes
@@ -1,4 +1,5 @@
*.mn NHSUBST
+*.tex NHSUBST
*.6 NHSUBST
*.7 NHSUBST
fixes* NHSUBST
@@ -10,3 +11,8 @@ tmac.nh NUSUBST
fixes* NH_header=no
*.txt NH_header=no
* NH_filestag=(file%s_for_all_versions)
+Guidebook.tex NH_DATESUB
+Guidebook.mn NH_DATESUB NHAUTODOCS
+*.6 NH_DATESUB NHAUTODOCS
+*.7 NH_DATESUB NHAUTODOCS
+fixes* -NHAUTODOCS
diff --git a/doc/.gitignore b/doc/.gitignore
index 8189eeacdf..f96d534c20 100644
--- a/doc/.gitignore
+++ b/doc/.gitignore
@@ -2,6 +2,10 @@
# latter is managed by git because it is part of the source distribution.
# We don't want both copies.
Guidebook
+# Unpaginated copy of Guidebook.txt that might someday be used for help
+# text to display within the game. If that happens and it gets added to
+# the distribution, it will live in dat/ rather than doc/.
+Guidebook.dat
# various intermediate files or generated output, not to be tracked.
Guidebook.aux
Guidebook.dvi
diff --git a/doc/Gbk-1pg-pfx.mn b/doc/Gbk-1pg-pfx.mn
new file mode 100644
index 0000000000..f59f621599
--- /dev/null
+++ b/doc/Gbk-1pg-pfx.mn
@@ -0,0 +1,3 @@
+.\" prefix to Guidebook.mn for 'roff version of Guidebook written as one page
+.
+.pl 12345v \" set page size of 12345 lines
diff --git a/doc/Gbk-1pg-sfx.mn b/doc/Gbk-1pg-sfx.mn
new file mode 100644
index 0000000000..d00b37f5fa
--- /dev/null
+++ b/doc/Gbk-1pg-sfx.mn
@@ -0,0 +1,8 @@
+.\" suffux to Guidebook.mn for 'roff version of Guidebook written as one page
+.br
+.\" add a marker that precedes hundreds of blank lines which pad out the page
+EOF--EOF
+.
+.\" post process with "sed -e '/EOF--EOF/,12345D'" to remove trailing junk
+.\" (also removes Unix trademark footnote; that ought to be kept but the
+.\" generic "all trademarks are held by respective owners" is still present)
diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn
index bad63a86a1..63abbbf1ff 100644
--- a/doc/Guidebook.mn
+++ b/doc/Guidebook.mn
@@ -13,18 +13,42 @@
.\"| is handled differently depending on whether it terminates an abbrevi-
.\"| ation or a sentence. To distinguish both cases, do a line break af-
.\"| ter each sentence.
-.\"|||
+.\"+--
+.\" Guidebook.mn has been updated to adhere to the first two guidelines
+.\" but does not yet fully honor the third. New changes should do so.
.\"
.
-.so tmac.nh \" extra macros which aren't in tmac.n
+.\" Usage:
+.\" to produce Guidebook.ps:
+.\" cat Guidebook.mn |tbl tmac.n - |groff >Guidebook.ps
+.\" to produce Guidebook.txt:
+.\" cat Guidebook.mn |tbl tmac.n - |groff -c -Tascii |col -bx >Guidebook.txt
+.\" with an optional filtering step between 'cat' and 'tbl':
+.\" cat... |../util/makedefs --grep --input - --output - |tbl...
+.
+.if n \{\
+.po 5n
+.ll 70n
+.lt 70n
+.\}
+.
+.so tmac.nh \" extra macros which aren't in tmac.n
+.if !\n(nH .so doc/tmac.nh
.
-.ds h0 "NetHack Guidebook
-.ds h1
+.\" 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
+.\" proceeded so lack of CR (fixed-width, moot for plain text) didn't matter
+.if n .do ftr CR R \" if formatting for a terminal, substitute R for CR
+. \" (the substitution affects both '\f' and '.ft')
+.
+.ds h0 NetHack Guidebook
+.ds h1 \" empty
.ds h2 %
-.ds vr "NetHack 3.6
-.ds f0 "\*(vr
-.ds f1
-.ds f2 "March 8, 2020
+.ds vr NetHack 3.6.7
+.ds f0 \*(vr
+.ds f1 \" empty
+.\"DO NOT REMOVE NH_DATESUB .ds f2 Date(%B %-d, %Y)
+.ds f2 February 3, 2023
.
.\" A note on some special characters:
.\" \(lq = left double quote
@@ -32,9 +56,11 @@
.\" \(oq = left (open) single quote
.\" \(cq = right (close) single quote \(aq = apostrophe / single quote
.\" - = hyphen \- = minus sign
-.\" \(em = M-sized dash
+.\" \(rs = backslash \(em = dash as wide as 'M' is tall
.\" ^ = small circumflex punctuation \(ha = larger circumflex character
.\" ~ = small tilde punctuation \(ti = larger tilde character
+.\"
+.\" See groff_man_style(7) or groff_char(7) for more on these.
.
.
.\" finally, start the actual Guidebook...
@@ -44,7 +70,7 @@ A Guide to the Mazes of Menace
(Guidebook for NetHack)
.au
Original version - Eric S. Raymond
-(Edited and expanded for 3.6 by Mike Stephenson and others)
+(Edited and expanded for \*(vr by Mike Stephenson and others)
.sp 1
\*(f2
.hn 1
@@ -92,7 +118,7 @@ travel, you see the ancient ruins that mark the entrance to the
Mazes of Menace. It is late at night, so you make camp at the entrance
and spend the night sleeping under the open skies. In the morning, you
gather your gear, eat what may be your last meal outside, and enter the
-dungeon...
+dungeon....
.
.hn 1
What is going on here?
@@ -229,9 +255,20 @@ replaces the \(lqYou see ...\(rq descriptions of text adventure games.
Figure 1 is a sample of what a NetHack screen might look like.
The way the screen looks for you depends on your platform.
.
+.\" (Either generated by hand or else the composite of two different
+.\" situations. Originally the character had only reached a second room
+.\" (unchanged here) by turn 257 (now changed to 752) and was already
+.\" Weak from hunger (now changed to just Hungry) and also lacked any of
+.\" Tourist's starting gold. Confusion is added to include a
+.\" condition.)
+.\"
+.\" Width is constrained by the margins of plain text output
+.\" (Guidebook.txt). Text output might show an extra space inboard of
+.\" the left and right box boundaries that does not appear in PostScript
+.\" output. This behavior is specific to GNU tbl.
.BR 2
.ft CR \" set font to constant-width Roman
-.TS S
+.TS
center box tab(~);
L.
The bat bites!
@@ -245,12 +282,28 @@ The bat bites!
-Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral
-Dlvl:1 $:0 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:257 Weak
+Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral
+Dlvl:1 $:993 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:752 Hungry Conf
.TE
-.ft \" revert to previous font
+.ft R
.ce 1
-Figure 1
+.if t .sp 0.5v
+ Figure 1
+.
+.BR 1
+.ft CR
+.TS
+center box tab(~);
+L.
+.\" Use trailing spaces to force the same width as Figure 1.
+Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 \&
+Neutral $:993 HP:9(12) Pw:3(3) AC:10 Exp:1/19 Hungry \&
+Dlvl:1 T:752 Conf \&
+.TE
+.ft R
+.ce 1
+.if t .sp 0.5v
+Figure 2
.
.hn 2
The status lines (bottom)
@@ -264,6 +317,11 @@ below):
.lp "Rank "
Your character's name and professional ranking (based on the
experience level, see below).
+.pg
+Here are explanations of what the various status items mean:
+.lp "Title "
+Your character's name and professional ranking (based on role and
+\fIexperience level\fP, see below).
.lp Strength
A measure of your character's strength; one of your six basic
attributes. A human character's attributes can range from 3 to 18 inclusive;
@@ -284,7 +342,7 @@ can carry. With sufficiently high strength, the contribution to
carrying capacity from your constitution no longer matters.
.lp Intelligence
Intelligence affects your ability to cast spells and read spellbooks.
-.lp Wisdom
+.lp "Wisdom "
Wisdom comes from your practical experience (especially when dealing with
magic). It affects your magical energy.
.lp Charisma
@@ -302,7 +360,7 @@ How deep you are in the dungeon. You start at level one and the number
increases as you go deeper into the dungeon. Some levels are special,
and are identified by a name and not a number. The Amulet of Yendor is
reputed to be somewhere beneath the twentieth level.
-.lp "Gold "
+.lp "Gold "
The number of gold pieces you are openly carrying. Gold which you have
concealed in containers is not counted.
.lp "Hit Points"
@@ -311,21 +369,23 @@ damage you can take before you die. The more you get hit in a fight,
the lower they get. You can regain hit points by resting, or by using
certain magical items or spells. The number in parentheses is the maximum
number your hit points can reach.
-.lp Power
+.lp "Power "
Spell points. This tells you how much mystic energy (\fImana\fP)
you have available for spell casting. Again, resting will regenerate the
amount available.
.lp "Armor Class"
A measure of how effectively your armor stops blows from unfriendly
-creatures. The lower this number is, the more effective the armor; it
+creatures.
+The lower this number is, the more effective the armor; it
is quite possible to have negative armor class.
+See the \fIArmor\fP subsection of \fIObjects\fP for more information.
.lp Experience
Your current experience level and experience points. As you
adventure, you gain experience points. At certain experience point
totals, you gain an experience level. The more experienced you are,
the better you fight and withstand magical attacks. Many dungeons
show only your experience level here.
-.lp "Time "
+.lp "Time "
The number of turns elapsed so far, displayed if you have the
.op time
option set.
@@ -2460,7 +2520,7 @@ Persistence of Objects
.pg
Normally, if you have seen an object at a particular map location and
move to another location where you can't directly see that object any
-more, if will continue to be displayed on your map.
+more, it will continue to be displayed on your map.
That remains the case even if it is not actually there any more \(em
perhaps a monster has picked it up or it has rotted away \(em
until you can see or feel that location again.
@@ -2636,12 +2696,12 @@ The file may not exist, but it is a normal ASCII text file and
can be created with any text editor.
.pg
On Windows, it is \(lq.nethackrc\(rq in the folder
-\(lq\\%USERPROFILE%\\NetHack\\3.6\(rq. The file may not exist,
+\(lq\\%USERPROFILE%\\NetHack\\(rq. The file may not exist,
but it is a normal ASCII text file can can be created with any
text editor.
After running NetHack for the first time, you should find a default
template for the configuration file named \(lq.nethackrc.template\(rq
-in \(lq\\%USERPROFILE%\\NetHack\\3.6\(rq.
+in \(lq\\%USERPROFILE%\\NetHack\\(rq.
If you had not created the configuration file, NetHack will create
the configuration file for you using the default template file.
.pg
@@ -3787,11 +3847,10 @@ Platform-specific Customization options
.pg
Here are explanations of options that are used by specific platforms or ports
to customize and change the port behavior.
-.lp altkeyhandler
-Select an alternate keystroke handler dll to load (Win32 tty NetHack only).
-The name of the handler is specified without the .dll extension and without
-any path information.
-Cannot be set with the \(oqO\(cq command.
+.lp altkeyhandling
+Select an alternate way to handle keystrokes (Win32 tty NetHack only).
+The name of the handling type is one of \(lqdefault\(rq, \(lqray\(rq,
+\(lq340\(rq.
.lp altmeta
On Amiga, this option controls whether typing \(lqAlt\(rq plus another key
functions as a meta-shift for that key (default on).
@@ -5167,31 +5226,39 @@ and a small number of bug fixes.
NetHack 3.6.6 was released on March 8, 2020 containing a security fix and
some bug fixes.
.pg
+NetHack 3.6.7 was released in February 2023 containing a security fix and
+some bug fixes.
+.pg
The official NetHack web site is maintained by \fBKen Lorber\fP
at
.UR https://www.nethack.org/ .
.pg
.hn 2
-SPECIAL THANKS
+Special Thanks
.pg
On behalf of the NetHack community, thank you very much once
again to \fBM. Drew Streib\fP and \fBPasi Kallinen\fP for providing a
public NetHack server at nethack.alt.org. Thanks to \fBKeith Simpson\fP
and \fBAndy Thomson\fP for hardfought.org. Thanks to all those
unnamed dungeoneers who invest their time and effort into annual
-NetHack tournaments such as Junethack, The November NetHack Tournament
+NetHack tournaments such as Junethack, The November NetHack Tournament,
and in days past, devnull.net (gone for now, but not forgotten).
+.\" .pg
+.\" .ce
+.\" - - - - - - - - - -\ \ \ \ \" when centered, the dashes look a little too
+.\" . \" far to right, so pad them with a few spaces
+.BR 1
.pg
-.ce
-- - - - - - - - - -\ \ \ \ \" when centered, the dashes look a little too far
-. \" to the right, so pad them with a few spaces
+.hn 2
+Dungeoneers
.pg
From time to time, some depraved individual out there in netland sends a
particularly intriguing modification to help out with the game. The NetHack
Development Team sometimes makes note of the names of the worst of these
miscreants in this, the list of Dungeoneers:
+.BR 1
.
-.TS S
+.TS
center;
c2 c2 c.
.\"TABLE_START
@@ -5239,6 +5306,7 @@ Irina Rempt-Drijfhout Mike Passaretti
Izchak Miller Mike Stephenson
.\"TABLE_END Do not delete this line.
.TE
+.BR 1
.pg
.\"Microsoft and MS-DOS are registered trademarks of Microsoft Corporation.
.\"Lattice is a trademark of Lattice, Inc.
diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex
index c34f6fa806..7d9e320e2d 100644
--- a/doc/Guidebook.tex
+++ b/doc/Guidebook.tex
@@ -45,7 +45,7 @@
%.au
\author{Original version - Eric S. Raymond\\
(Edited and expanded for 3.6 by Mike Stephenson and others)}
-\date{March 8, 2020}
+\date{February 3, 2023}
\maketitle
@@ -2707,7 +2707,7 @@ \subsection*{Persistence of Objects}
%.pg
Normally, if you have seen an object at a particular map location and
move to another location where you can't directly see that object any
-more, if will continue to be displayed on your map.
+more, it will continue to be displayed on your map.
That remains the case even if it is not actually there any
more---perhaps a monster has picked it up or it has rotted
away---until you can see or feel that location again.
@@ -2883,12 +2883,12 @@ \subsection*{Using a configuration file}
%.lp ""
On Windows, it is \mbox{``.nethackrc''} in the folder
-\mbox{{``\%USERPROFILE\%\textbackslash NetHack\textbackslash 3.6''}}. The
+\mbox{{``\%USERPROFILE\%\textbackslash NetHack\textbackslash''}}. The
file may not exist, but it is a normal ASCII text file and can be created
with any text editor.
After runing {\it NetHack\/} for the first time, you should find a default
template for ths configuration file named \mbox{``.nethackrc.template''} in
-\mbox{{``\%USERPROFILE\%\textbackslash NetHack\textbackslash 3.6''}}.
+\mbox{{``\%USERPROFILE\%\textbackslash NetHack\textbackslash''}}.
If you had not created the configuration file, {\it NetHack\/} will create
the configuration file for you using the default template file.
@@ -4211,11 +4211,9 @@ \subsection*{Platform-specific Customization options}
\blist{}
%.lp
-\item[\ib{altkeyhandler}]
-Select an alternate keystroke handler dll to load ({\it Win32 tty\/ NetHack\/} only).
-The name of the handler is specified without the .dll extension and without any
-path information.
-Cannot be set with the `{\tt O}' command.
+\item[\ib{altkeyhandling}]
+Select an alternate way to handle keystrokes ({\it Win32 tty\/ NetHack\/} only).
+The name of the handling type is one of {\it default}, {\it ray}, {\it 340}
%.lp
\item[\ib{altmeta}]
On Amiga, this option controls whether typing ``Alt'' plus another key
@@ -5778,6 +5776,11 @@ \section{Credits}
NetHack 3.6.6 was released on March 8, 2020 containing a security fix and
some bug fixes.
+%.pg
+\medskip
+NetHack 3.6.7 was released in February 2023 containing a security fix and
+some bug fixes.
+
%.pg
\medskip
\nd The official {\it NetHack\/} web site is maintained by {\it Ken Lorber} at
diff --git a/doc/Guidebook.txt b/doc/Guidebook.txt
index 7a9234dbef..ee4b3021d2 100644
--- a/doc/Guidebook.txt
+++ b/doc/Guidebook.txt
@@ -8,245 +8,234 @@
- A Guide to the Mazes of Menace
- (Guidebook for NetHack)
+ A Guide to the Mazes of Menace
+ (Guidebook for NetHack)
- Original version - Eric S. Raymond
- (Edited and expanded for 3.6 by Mike Stephenson and others)
+ Original version - Eric S. Raymond
+ (Edited and expanded for NetHack 3.6.7 by Mike Stephenson and others)
- March 4, 2020
+ February 3, 2023
- 1. Introduction
+ 1. Introduction
- Recently, you have begun to find yourself unfulfilled and
- distant in your daily occupation. Strange dreams of prospecting,
- stealing, crusading, and combat have haunted you in your sleep
- for many months, but you aren't sure of the reason. You wonder
- whether you have in fact been having those dreams all your life,
- and somehow managed to forget about them until now. Some nights
- you awaken suddenly and cry out, terrified at the vivid recollec-
- tion of the strange and powerful creatures that seem to be lurk-
- ing behind every corner of the dungeon in your dream. Could
- these details haunting your dreams be real? As each night pass-
- es, you feel the desire to enter the mysterious caverns near the
- ruins grow stronger. Each morning, however, you quickly put the
- idea out of your head as you recall the tales of those who en-
- tered the caverns before you and did not return. Eventually you
- can resist the yearning to seek out the fantastic place in your
- dreams no longer. After all, when other adventurers came back
- this way after spending time in the caverns, they usually seemed
- better off than when they passed through the first time. And who
- was to say that all of those who did not return had not just kept
- going?
+ Recently, you have begun to find yourself unfulfilled and distant
+ in your daily occupation. Strange dreams of prospecting, stealing,
+ crusading, and combat have haunted you in your sleep for many months,
+ but you aren't sure of the reason. You wonder whether you have in
+ fact been having those dreams all your life, and somehow managed to
+ forget about them until now. Some nights you awaken suddenly and cry
+ out, terrified at the vivid recollection of the strange and powerful
+ creatures that seem to be lurking behind every corner of the dungeon
+ in your dream. Could these details haunting your dreams be real? As
+ each night passes, you feel the desire to enter the mysterious caverns
+ near the ruins grow stronger. Each morning, however, you quickly put
+ the idea out of your head as you recall the tales of those who entered
+ the caverns before you and did not return. Eventually you can resist
+ the yearning to seek out the fantastic place in your dreams no longer.
+ After all, when other adventurers came back this way after spending
+ time in the caverns, they usually seemed better off than when they
+ passed through the first time. And who was to say that all of those
+ who did not return had not just kept going?
- Asking around, you hear about a bauble, called the Amulet of
- Yendor by some, which, if you can find it, will bring you great
- wealth. One legend you were told even mentioned that the one who
- finds the amulet will be granted immortality by the gods. The
- amulet is rumored to be somewhere beyond the Valley of Gehennom,
- deep within the Mazes of Menace. Upon hearing the legends, you
- immediately realize that there is some profound and undiscovered
- reason that you are to descend into the caverns and seek out that
- amulet of which they spoke. Even if the rumors of the amulet's
- powers are untrue, you decide that you should at least be able to
- sell the tales of your adventures to the local minstrels for a
- tidy sum, especially if you encounter any of the terrifying and
- magical creatures of your dreams along the way. You spend one
- last night fortifying yourself at the local inn, becoming more
- and more depressed as you watch the odds of your success being
- posted on the inn's walls getting lower and lower.
+ Asking around, you hear about a bauble, called the Amulet of Yen-
+ dor by some, which, if you can find it, will bring you great wealth.
+ One legend you were told even mentioned that the one who finds the
+ amulet will be granted immortality by the gods. The amulet is rumored
+ to be somewhere beyond the Valley of Gehennom, deep within the Mazes
+ of Menace. Upon hearing the legends, you immediately realize that
+ there is some profound and undiscovered reason that you are to descend
+ into the caverns and seek out that amulet of which they spoke. Even
+ if the rumors of the amulet's powers are untrue, you decide that you
+ should at least be able to sell the tales of your adventures to the
+ local minstrels for a tidy sum, especially if you encounter any of the
+ terrifying and magical creatures of your dreams along the way. You
+ spend one last night fortifying yourself at the local inn, becoming
+ more and more depressed as you watch the odds of your success being
+ posted on the inn's walls getting lower and lower.
+ In the morning you awake, collect your belongings, and set off
+ for the dungeon. After several days of uneventful travel, you see the
- NetHack Guidebook 1
+ NetHack Guidebook 1
- NetHack Guidebook 2
+ NetHack Guidebook 2
- In the morning you awake, collect your belongings, and set
- off for the dungeon. After several days of uneventful travel,
- you see the ancient ruins that mark the entrance to the Mazes of
- Menace. It is late at night, so you make camp at the entrance
- and spend the night sleeping under the open skies. In the morn-
- ing, you gather your gear, eat what may be your last meal out-
- side, and enter the dungeon...
- 2. What is going on here?
+ ancient ruins that mark the entrance to the Mazes of Menace. It is
+ late at night, so you make camp at the entrance and spend the night
+ sleeping under the open skies. In the morning, you gather your gear,
+ eat what may be your last meal outside, and enter the dungeon....
- You have just begun a game of NetHack. Your goal is to grab
- as much treasure as you can, retrieve the Amulet of Yendor, and
- escape the Mazes of Menace alive.
+ 2. What is going on here?
- Your abilities and strengths for dealing with the hazards of
- adventure will vary with your background and training:
+ You have just begun a game of NetHack. Your goal is to grab as
+ much treasure as you can, retrieve the Amulet of Yendor, and escape
+ the Mazes of Menace alive.
- Archeologists understand dungeons pretty well; this enables
- them to move quickly and sneak up on the local nasties. They
- start equipped with the tools for a proper scientific expedition.
+ Your abilities and strengths for dealing with the hazards of
+ adventure will vary with your background and training:
- Barbarians are warriors out of the hinterland, hardened to
- battle. They begin their quests with naught but uncommon
- strength, a trusty hauberk, and a great two-handed sword.
+ Archeologists understand dungeons pretty well; this enables them
+ to move quickly and sneak up on the local nasties. They start
+ equipped with the tools for a proper scientific expedition.
- Cavemen and Cavewomen start with exceptional strength but,
- unfortunately, with neolithic weapons.
+ Barbarians are warriors out of the hinterland, hardened to bat-
+ tle. They begin their quests with naught but uncommon strength, a
+ trusty hauberk, and a great two-handed sword.
- Healers are wise in medicine and apothecary. They know the
- herbs and simples that can restore vitality, ease pain, anes-
- thetize, and neutralize poisons; and with their instruments, they
- can divine a being's state of health or sickness. Their medical
- practice earns them quite reasonable amounts of money, with which
- they enter the dungeon.
+ Cavemen and Cavewomen start with exceptional strength but, unfor-
+ tunately, with neolithic weapons.
- Knights are distinguished from the common skirmisher by
- their devotion to the ideals of chivalry and by the surpassing
- excellence of their armor.
+ Healers are wise in medicine and apothecary. They know the herbs
+ and simples that can restore vitality, ease pain, anesthetize, and
+ neutralize poisons; and with their instruments, they can divine a
+ being's state of health or sickness. Their medical practice earns
+ them quite reasonable amounts of money, with which they enter the dun-
+ geon.
- Monks are ascetics, who by rigorous practice of physical and
- mental disciplines have become capable of fighting as effectively
- without weapons as with. They wear no armor but make up for it
- with increased mobility.
+ Knights are distinguished from the common skirmisher by their
+ devotion to the ideals of chivalry and by the surpassing excellence of
+ their armor.
- Priests and Priestesses are clerics militant, crusaders ad-
- vancing the cause of righteousness with arms, armor, and arts
- thaumaturgic. Their ability to commune with deities via prayer
- occasionally extricates them from peril, but can also put them in
- it.
+ Monks are ascetics, who by rigorous practice of physical and men-
+ tal disciplines have become capable of fighting as effectively without
+ weapons as with. They wear no armor but make up for it with increased
+ mobility.
- Rangers are most at home in the woods, and some say slightly
- out of place in a dungeon. They are, however, experts in archery
- as well as tracking and stealthy movement.
+ Priests and Priestesses are clerics militant, crusaders advancing
+ the cause of righteousness with arms, armor, and arts thaumaturgic.
+ Their ability to commune with deities via prayer occasionally extri-
+ cates them from peril, but can also put them in it.
+ Rangers are most at home in the woods, and some say slightly out
+ of place in a dungeon. They are, however, experts in archery as well
+ as tracking and stealthy movement.
+ Rogues are agile and stealthy thieves, with knowledge of locks,
+ traps, and poisons. Their advantage lies in surprise, which they
+ employ to great advantage.
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 3
+ NetHack Guidebook 3
- Rogues are agile and stealthy thieves, with knowledge of
- locks, traps, and poisons. Their advantage lies in surprise,
- which they employ to great advantage.
- Samurai are the elite warriors of feudal Nippon. They are
- lightly armored and quick, and wear the dai-sho, two swords of
- the deadliest keenness.
- Tourists start out with lots of gold (suitable for shopping
- with), a credit card, lots of food, some maps, and an expensive
- camera. Most monsters don't like being photographed.
+ Samurai are the elite warriors of feudal Nippon. They are
+ lightly armored and quick, and wear the dai-sho, two swords of the
+ deadliest keenness.
- Valkyries are hardy warrior women. Their upbringing in the
- harsh Northlands makes them strong, inures them to extremes of
- cold, and instills in them stealth and cunning.
+ Tourists start out with lots of gold (suitable for shopping
+ with), a credit card, lots of food, some maps, and an expensive cam-
+ era. Most monsters don't like being photographed.
- Wizards start out with a knowledge of magic, a selection of
- magical items, and a particular affinity for dweomercraft. Al-
- though seemingly weak and easy to overcome at first sight, an ex-
- perienced Wizard is a deadly foe.
+ Valkyries are hardy warrior women. Their upbringing in the harsh
+ Northlands makes them strong, inures them to extremes of cold, and
+ instills in them stealth and cunning.
- You may also choose the race of your character (within lim-
- its; most roles have restrictions on which races are eligible for
- them):
+ Wizards start out with a knowledge of magic, a selection of magi-
+ cal items, and a particular affinity for dweomercraft. Although seem-
+ ingly weak and easy to overcome at first sight, an experienced Wizard
+ is a deadly foe.
- Dwarves are smaller than humans or elves, but are stocky and
- solid individuals. Dwarves' most notable trait is their great
- expertise in mining and metalwork. Dwarvish armor is said to be
- second in quality not even to the mithril armor of the Elves.
+ You may also choose the race of your character (within limits;
+ most roles have restrictions on which races are eligible for them):
- Elves are agile, quick, and perceptive; very little of what
- goes on will escape an Elf. The quality of Elven craftsmanship
- often gives them an advantage in arms and armor.
+ Dwarves are smaller than humans or elves, but are stocky and
+ solid individuals. Dwarves' most notable trait is their great exper-
+ tise in mining and metalwork. Dwarvish armor is said to be second in
+ quality not even to the mithril armor of the Elves.
- Gnomes are smaller than but generally similar to dwarves.
- Gnomes are known to be expert miners, and it is known that a se-
- cret underground mine complex built by this race exists within
- the Mazes of Menace, filled with both riches and danger.
+ Elves are agile, quick, and perceptive; very little of what goes
+ on will escape an Elf. The quality of Elven craftsmanship often gives
+ them an advantage in arms and armor.
- Humans are by far the most common race of the surface world,
- and are thus the norm to which other races are often compared.
- Although they have no special abilities, they can succeed in any
- role.
+ Gnomes are smaller than but generally similar to dwarves. Gnomes
+ are known to be expert miners, and it is known that a secret under-
+ ground mine complex built by this race exists within the Mazes of Men-
+ ace, filled with both riches and danger.
- Orcs are a cruel and barbaric race that hate every living
- thing (including other orcs). Above all others, Orcs hate Elves
- with a passion unequalled, and will go out of their way to kill
- one at any opportunity. The armor and weapons fashioned by the
- Orcs are typically of inferior quality.
+ Humans are by far the most common race of the surface world, and
+ are thus the norm to which other races are often compared. Although
+ they have no special abilities, they can succeed in any role.
- 3. What do all those things on the screen mean?
+ Orcs are a cruel and barbaric race that hate every living thing
+ (including other orcs). Above all others, Orcs hate Elves with a pas-
+ sion unequalled, and will go out of their way to kill one at any
+ opportunity. The armor and weapons fashioned by the Orcs are typi-
+ cally of inferior quality.
- On the screen is kept a map of where you have been and what
- you have seen on the current dungeon level; as you explore more
+ 3. What do all those things on the screen mean?
+ On the screen is kept a map of where you have been and what you
+ have seen on the current dungeon level; as you explore more of the
+ level, it appears on the screen in front of you.
- NetHack 3.6 March 4, 2020
+ When NetHack's ancestor rogue first appeared, its screen orienta-
+ tion was almost unique among computer fantasy games. Since then,
+ screen orientation has become the norm rather than the exception;
+ NetHack continues this fine tradition. Unlike text adventure games
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 4
+ NetHack Guidebook 4
- of the level, it appears on the screen in front of you.
- When NetHack's ancestor rogue first appeared, its screen
- orientation was almost unique among computer fantasy games.
- Since then, screen orientation has become the norm rather than
- the exception; NetHack continues this fine tradition. Unlike
- text adventure games that accept commands in pseudo-English sen-
- tences and explain the results in words, NetHack commands are all
- one or two keystrokes and the results are displayed graphically
- on the screen. A minimum screen size of 24 lines by 80 columns
- is recommended; if the screen is larger, only a 21x80 section
- will be used for the map.
- NetHack can even be played by blind players, with the assis-
- tance of Braille readers or speech synthesisers. Instructions
- for configuring NetHack for the blind are included later in this
- document.
+ that accept commands in pseudo-English sentences and explain the
+ results in words, NetHack commands are all one or two keystrokes and
+ the results are displayed graphically on the screen. A minimum screen
+ size of 24 lines by 80 columns is recommended; if the screen is
+ larger, only a 21x80 section will be used for the map.
- NetHack generates a new dungeon every time you play it; even
- the authors still find it an entertaining and exciting game de-
- spite having won several times.
+ NetHack can even be played by blind players, with the assistance
+ of Braille readers or speech synthesisers. Instructions for configur-
+ ing NetHack for the blind are included later in this document.
- NetHack offers a variety of display options. The options
- available to you will vary from port to port, depending on the
- capabilities of your hardware and software, and whether various
- compile-time options were enabled when your executable was creat-
- ed. The three possible display options are: a monochrome charac-
- ter interface, a color character interface, and a graphical in-
- terface using small pictures called tiles. The two character in-
- terfaces allow fonts with other characters to be substituted, but
- the default assignments use standard ASCII characters to repre-
- sent everything. There is no difference between the various dis-
- play options with respect to game play. Because we cannot repro-
- duce the tiles or colors in the Guidebook, and because it is com-
- mon to all ports, we will use the default ASCII characters from
- the monochrome character display when referring to things you
- might see on the screen during your game.
+ NetHack generates a new dungeon every time you play it; even the
+ authors still find it an entertaining and exciting game despite having
+ won several times.
- In order to understand what is going on in NetHack, first
- you must understand what NetHack is doing with the screen. The
- NetHack screen replaces the "You see ..." descriptions of text
- adventure games. Figure 1 is a sample of what a NetHack screen
- might look like. The way the screen looks for you depends on
- your platform.
+ NetHack offers a variety of display options. The options avail-
+ able to you will vary from port to port, depending on the capabilities
+ of your hardware and software, and whether various compile-time
+ options were enabled when your executable was created. The three pos-
+ sible display options are: a monochrome character interface, a color
+ character interface, and a graphical interface using small pictures
+ called tiles. The two character interfaces allow fonts with other
+ characters to be substituted, but the default assignments use standard
+ ASCII characters to represent everything. There is no difference
+ between the various display options with respect to game play.
+ Because we cannot reproduce the tiles or colors in the Guidebook, and
+ because it is common to all ports, we will use the default ASCII char-
+ acters from the monochrome character display when referring to things
+ you might see on the screen during your game.
+ In order to understand what is going on in NetHack, first you
+ must understand what NetHack is doing with the screen. The NetHack
+ screen replaces the "You see ..." descriptions of text adventure
+ games. Figure 1 is a sample of what a NetHack screen might look like.
+ The way the screen looks for you depends on your platform.
@@ -258,5872 +247,5883 @@
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 5
- +----------------------------------------------------------------+
- |The bat bites! |
- | |
- | ------ |
- | |....| ---------- |
- | |.<..|####...@...$.| |
- | |....-# |...B....+ |
- | |....| |.d......| |
- | ------ -------|-- |
- | |
- | |
- | |
- |Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral |
- |Dlvl:1 $:0 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:257 Weak |
- +---------------------------Figure-1-----------------------------+
- 3.1. The status lines (bottom)
- The bottom two lines of the screen contain several cryptic
- pieces of information describing your current status. If either
- status line becomes longer than the width of the screen, you
- might not see all of it. Here are explanations of what the vari-
- ous status items mean (though your configuration may not have all
- the status items listed below):
- Rank
- Your character's name and professional ranking (based on the
- experience level, see below).
+ NetHack 3.6.7 February 3, 2023
- Strength
- A measure of your character's strength; one of your six ba-
- sic attributes. A human character's attributes can range
- from 3 to 18 inclusive; non-humans may exceed these limits
- (occasionally you may get super-strengths of the form 18/xx,
- and magic can also cause attributes to exceed the normal
- limits). The higher your strength, the stronger you are.
- Strength affects how successfully you perform physical
- tasks, how much damage you do in combat, and how much loot
- you can carry.
- Dexterity
- Dexterity affects your chances to hit in combat, to avoid
- traps, and do other tasks requiring agility or manipulation
- of objects.
- Constitution
- Constitution affects your ability to recover from injuries
- and other strains on your stamina. When strength is low or
- modest, constitution also affects how much you can carry.
- With sufficiently high strength, the contribution to carry-
- ing capacity from your constitution no longer matters.
- Intelligence
- Intelligence affects your ability to cast spells and read
+ NetHack Guidebook 5
- NetHack 3.6 March 4, 2020
+ +---------------------------------------------------------------+
+ |The bat bites! |
+ | |
+ | ------ |
+ | |....| ---------- |
+ | |.<..|####...@...$.| |
+ | |....-# |...B....+ |
+ | |....| |.d......| |
+ | ------ -------|-- |
+ | |
+ | |
+ | |
+ |Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral |
+ |Dlvl:1 $:993 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:752 Hungry Conf |
+ +---------------------------Figure-1----------------------------+
- NetHack Guidebook 6
- spellbooks.
- Wisdom
- Wisdom comes from your practical experience (especially when
- dealing with magic). It affects your magical energy.
- Charisma
- Charisma affects how certain creatures react toward you. In
- particular, it can affect the prices shopkeepers offer you.
- Alignment
- Lawful, Neutral, or Chaotic. Often, Lawful is taken as good
- and Chaotic as evil, but legal and ethical do not always co-
- incide. Your alignment influences how other monsters react
- toward you. Monsters of a like alignment are more likely to
- be non-aggressive, while those of an opposing alignment are
- more likely to be seriously offended at your presence.
- Dungeon Level
- How deep you are in the dungeon. You start at level one and
- the number increases as you go deeper into the dungeon.
- Some levels are special, and are identified by a name and
- not a number. The Amulet of Yendor is reputed to be some-
- where beneath the twentieth level.
- Gold
- The number of gold pieces you are openly carrying. Gold
- which you have concealed in containers is not counted.
- Hit Points
- Your current and maximum hit points. Hit points indicate
- how much damage you can take before you die. The more you
- get hit in a fight, the lower they get. You can regain hit
- points by resting, or by using certain magical items or
- spells. The number in parentheses is the maximum number
- your hit points can reach.
- Power
- Spell points. This tells you how much mystic energy (mana)
- you have available for spell casting. Again, resting will
- regenerate the amount available.
- Armor Class
- A measure of how effectively your armor stops blows from un-
- friendly creatures. The lower this number is, the more ef-
- fective the armor; it is quite possible to have negative ar-
- mor class.
- Experience
- Your current experience level and experience points. As you
- adventure, you gain experience points. At certain experi-
- ence point totals, you gain an experience level. The more
- experienced you are, the better you fight and withstand mag-
- ical attacks. Many dungeons show only your experience level
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 7
- here.
- Time
- The number of turns elapsed so far, displayed if you have
- the time option set.
- Status
- Hunger: your current hunger status. Values are Satiated,
- Not Hungry (or Normal), Hungry, Weak, and Fainting. Not
- shown when Normal.
- Encumbrance: an indication of how what you are carrying af-
- fects your ability to move. Values are Unencumbered, Encum-
- bered, Stressed, Strained, Overtaxed, and Overloaded. Not
- shown when Unencumbered.
- Fatal conditions: Stone (aka Petrifying, turning to stone),
- Slime (turning into green slime), Strngl (being strangled),
- FoodPois (suffering from acute food poisoning), TermIll
- (suffering from a terminal illness).
- Non-fatal conditions: Blind (can't see), Deaf (can't hear),
- Stun (stunned), Conf (confused), Hallu (hallucinating).
- Movement modifiers: Lev (levitating), Fly (flying), Ride
- (riding).
- Other conditions and modifiers exist, but there isn't enough
- room to display them with the other status fields. The `^X'
- command shows all relevant status conditions.
- 3.2. The message line (top)
- The top line of the screen is reserved for messages that de-
- scribe things that are impossible to represent visually. If you
- see a "--More--" on the top line, this means that NetHack has an-
- other message to display on the screen, but it wants to make cer-
- tain that you've read the one that is there first. To read the
- next message, just press the space bar.
- To change how and what messages are shown on the message
- line, see "Configuring Message Types" and the verbose option.
- 3.3. The map (rest of the screen)
- The rest of the screen is the map of the level as you have
- explored it so far. Each symbol on the screen represents some-
- thing. You can set various graphics options to change some of
- the symbols the game uses; otherwise, the game will use default
- symbols. Here is a list of what the default symbols mean:
- - and |
- The walls of a room, or an open door. Or a grave (|).
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 8
+ NetHack Guidebook 6
- . The floor of a room, ice, or a doorless doorway.
+ +---------------------------------------------------------------+
+ |Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 |
+ |Neutral $:993 HP:9(12) Pw:3(3) AC:10 Exp:1/19 Hungry |
+ |Dlvl:1 T:752 Conf |
+ +---------------------------Figure-2----------------------------+
- # A corridor, or iron bars, or a tree, or possibly a kitchen
- sink (if your dungeon has sinks), or a drawbridge.
+ 3.1. The status lines (bottom)
- > Stairs down: a way to the next level.
+ The bottom two lines of the screen contain several cryptic pieces
+ of information describing your current status. If either status line
+ becomes longer than the width of the screen, you might not see all of
+ it. Here are explanations of what the various status items mean
+ (though your configuration may not have all the status items listed
+ below):
- < Stairs up: a way to the previous level.
+ Rank
+ Your character's name and professional ranking (based on the
+ experience level, see below).
- + A closed door, or a spellbook containing a spell you may be
- able to learn.
+ Here are explanations of what the various status items mean:
- @ Your character or a human.
+ Title
+ Your character's name and professional ranking (based on role and
+ experience level, see below).
- $ A pile of gold.
+ Strength
+ A measure of your character's strength; one of your six basic
+ attributes. A human character's attributes can range from 3 to
+ 18 inclusive; non-humans may exceed these limits (occasionally
+ you may get super-strengths of the form 18/xx, and magic can also
+ cause attributes to exceed the normal limits). The higher your
+ strength, the stronger you are. Strength affects how success-
+ fully you perform physical tasks, how much damage you do in com-
+ bat, and how much loot you can carry.
- ^ A trap (once you have detected it).
+ Dexterity
+ Dexterity affects your chances to hit in combat, to avoid traps,
+ and do other tasks requiring agility or manipulation of objects.
- ) A weapon.
+ Constitution
+ Constitution affects your ability to recover from injuries and
+ other strains on your stamina. When strength is low or modest,
+ constitution also affects how much you can carry. With suffi-
+ ciently high strength, the contribution to carrying capacity from
+ your constitution no longer matters.
- [ A suit or piece of armor.
+ Intelligence
+ Intelligence affects your ability to cast spells and read spell-
+ books.
- % Something edible (not necessarily healthy).
+ Wisdom
+ Wisdom comes from your practical experience (especially when
+ dealing with magic). It affects your magical energy.
- ? A scroll.
- / A wand.
- = A ring.
+ NetHack 3.6.7 February 3, 2023
- ! A potion.
- ( A useful item (pick-axe, key, lamp...).
- " An amulet or a spider web.
- * A gem or rock (possibly valuable, possibly worthless).
- ` A boulder or statue.
+ NetHack Guidebook 7
- 0 An iron ball.
- _ An altar, or an iron chain.
- { A fountain.
+ Charisma
+ Charisma affects how certain creatures react toward you. In par-
+ ticular, it can affect the prices shopkeepers offer you.
- } A pool of water or moat or a pool of lava.
+ Alignment
+ Lawful, Neutral, or Chaotic. Often, Lawful is taken as good and
+ Chaotic as evil, but legal and ethical do not always coincide.
+ Your alignment influences how other monsters react toward you.
+ Monsters of a like alignment are more likely to be non-aggres-
+ sive, while those of an opposing alignment are more likely to be
+ seriously offended at your presence.
- \ An opulent throne.
+ Dungeon Level
+ How deep you are in the dungeon. You start at level one and the
+ number increases as you go deeper into the dungeon. Some levels
+ are special, and are identified by a name and not a number. The
+ Amulet of Yendor is reputed to be somewhere beneath the twentieth
+ level.
- a-zA-Z and other symbols
- Letters and certain other symbols represent the various in-
- habitants of the Mazes of Menace. Watch out, they can be
- nasty and vicious. Sometimes, however, they can be helpful.
+ Gold
+ The number of gold pieces you are openly carrying. Gold which
+ you have concealed in containers is not counted.
+ Hit Points
+ Your current and maximum hit points. Hit points indicate how
+ much damage you can take before you die. The more you get hit in
+ a fight, the lower they get. You can regain hit points by rest-
+ ing, or by using certain magical items or spells. The number in
+ parentheses is the maximum number your hit points can reach.
- NetHack 3.6 March 4, 2020
+ Power
+ Spell points. This tells you how much mystic energy (mana) you
+ have available for spell casting. Again, resting will regenerate
+ the amount available.
+ Armor Class
+ A measure of how effectively your armor stops blows from
+ unfriendly creatures. The lower this number is, the more effec-
+ tive the armor; it is quite possible to have negative armor
+ class. See the Armor subsection of Objects for more information.
+ Experience
+ Your current experience level and experience points. As you
+ adventure, you gain experience points. At certain experience
+ point totals, you gain an experience level. The more experienced
+ you are, the better you fight and withstand magical attacks.
+ Many dungeons show only your experience level here.
+ Time
+ The number of turns elapsed so far, displayed if you have the
+ time option set.
+ Status
+ Hunger: your current hunger status. Values are Satiated, Not
- NetHack Guidebook 9
+ NetHack 3.6.7 February 3, 2023
- I This marks the last known location of an invisible or other-
- wise unseen monster. Note that the monster could have
- moved. The `F' and `m' commands may be useful here.
- You need not memorize all these symbols; you can ask the
- game what any symbol represents with the `/' command (see the
- next section for more info).
- 4. Commands
- Commands can be initiated by typing one or two characters to
- which the command is bound to, or typing the command name in the
- extended commands entry. Some commands, like "search", do not
- require that any more information be collected by NetHack. Other
- commands might require additional information, for example a di-
- rection, or an object to be used. For those commands that re-
- quire additional information, NetHack will present you with ei-
- ther a menu of choices or with a command line prompt requesting
- information. Which you are presented with will depend chiefly on
- how you have set the menustyle option.
+ NetHack Guidebook 8
- For example, a common question, in the form "What do you
- want to use? [a-zA-Z ?*]", asks you to choose an object you are
- carrying. Here, "a-zA-Z" are the inventory letters of your pos-
- sible choices. Typing `?' gives you an inventory list of these
- items, so you can see what each letter refers to. In this exam-
- ple, there is also a `*' indicating that you may choose an object
- not on the list, if you wanted to use something unexpected. Typ-
- ing a `*' lists your entire inventory, so you can see the inven-
- tory letters of every object you're carrying. Finally, if you
- change your mind and decide you don't want to do this command af-
- ter all, you can press the ESC key to abort the command.
- You can put a number before some commands to repeat them
- that many times; for example, "10s" will search ten times. If
- you have the number_pad option set, you must type `n' to prefix a
- count, so the example above would be typed "n10s" instead. Com-
- mands for which counts make no sense ignore them. In addition,
- movement commands can be prefixed for greater control (see be-
- low). To cancel a count or a prefix, press the ESC key.
- The list of commands is rather long, but it can be read at
- any time during the game through the `?' command, which accesses
- a menu of helpful texts. Here are the default key bindings for
- your reference:
+ Hungry (or Normal), Hungry, Weak, and Fainting. Not shown when
+ Normal.
- ? Help menu: display one of several help texts available.
+ Encumbrance: an indication of how what you are carrying affects
+ your ability to move. Values are Unencumbered, Encumbered,
+ Stressed, Strained, Overtaxed, and Overloaded. Not shown when
+ Unencumbered.
- / The "whatis" command, to tell what a symbol represents. You
- may choose to specify a location or type a symbol (or even a
- whole word) to explain. Specifying a location is done by
- moving the cursor to a particular spot on the map and then
- pressing one of `.', `,', `;', or `:'. `.' will explain the
- symbol at the chosen location, conditionally check for "More
+ Fatal conditions: Stone (aka Petrifying, turning to stone), Slime
+ (turning into green slime), Strngl (being strangled), FoodPois
+ (suffering from acute food poisoning), TermIll (suffering from a
+ terminal illness).
+ Non-fatal conditions: Blind (can't see), Deaf (can't hear), Stun
+ (stunned), Conf (confused), Hallu (hallucinating).
- NetHack 3.6 March 4, 2020
+ Movement modifiers: Lev (levitating), Fly (flying), Ride (rid-
+ ing).
+ Other conditions and modifiers exist, but there isn't enough room
+ to display them with the other status fields. The `^X' command
+ shows all relevant status conditions.
+ 3.2. The message line (top)
+ The top line of the screen is reserved for messages that describe
+ things that are impossible to represent visually. If you see a
+ "--More--" on the top line, this means that NetHack has another mes-
+ sage to display on the screen, but it wants to make certain that
+ you've read the one that is there first. To read the next message,
+ just press the space bar.
+ To change how and what messages are shown on the message line,
+ see "Configuring Message Types" and the verbose option.
- NetHack Guidebook 10
+ 3.3. The map (rest of the screen)
+ The rest of the screen is the map of the level as you have
+ explored it so far. Each symbol on the screen represents something.
+ You can set various graphics options to change some of the symbols the
+ game uses; otherwise, the game will use default symbols. Here is a
+ list of what the default symbols mean:
+ - and |
+ The walls of a room, or an open door. Or a grave (|).
- info?" depending upon whether the help option is on, and
- then you will be asked to pick another location; `,' will
- explain the symbol but skip any additional information, then
- let you pick another location; `;' will skip additional info
- and also not bother asking you to choose another location to
- examine; `:' will show additional info, if any, without ask-
- ing for confirmation. When picking a location, pressing the
- ESC key will terminate this command, or pressing `?' will
- give a brief reminder about how it works.
+ . The floor of a room, ice, or a doorless doorway.
- If the autodescribe option is on, a short description of
- what you see at each location is shown as you move the cur-
- sor. Typing `#' while picking a location will toggle that
- option on or off. The whatis_coord option controls whether
- the short description includes map coordinates.
+ # A corridor, or iron bars, or a tree, or possibly a kitchen sink
+ (if your dungeon has sinks), or a drawbridge.
- Specifying a name rather than a location always gives any
- additional information available about that name.
+ > Stairs down: a way to the next level.
- You may also request a description of nearby monsters, all
- monsters currently displayed, nearby objects, or all ob-
- jects. The whatis_coord option controls which format of map
- coordinate is included with their descriptions.
- & Tell what a command does.
- < Go up to the previous level (if you are on a staircase or
- ladder).
- > Go down to the next level (if you are on a staircase or lad-
- der).
+ NetHack 3.6.7 February 3, 2023
- [yuhjklbn]
- Go one step in the direction indicated (see Figure 2). If
- you sense or remember a monster there, you will fight the
- monster instead. Only these one-step movement commands
- cause you to fight monsters; the others (below) are "safe."
- y k u 7 8 9
- \ | / \ | /
- h- . -l 4- . -6
- / | \ / | \
- b j n 1 2 3
- (if number_pad is set)
- Figure 2
- [YUHJKLBN]
- Go in that direction until you hit a wall or run into some-
- thing.
- m[yuhjklbn]
- Prefix: move without picking up objects or fighting (even
- if you remember a monster there).
+ NetHack Guidebook 9
- NetHack 3.6 March 4, 2020
+ < Stairs up: a way to the previous level.
+ + A closed door, or a spellbook containing a spell you may be able
+ to learn.
+ @ Your character or a human.
+ $ A pile of gold.
- NetHack Guidebook 11
+ ^ A trap (once you have detected it).
+ ) A weapon.
+ [ A suit or piece of armor.
- A few non-movement commands use the `m' prefix to request
- operating via menu (to temporarily override the
- menustyle:Traditional option). Primarily useful for `,'
- (pickup) when there is only one class of objects present
- (where there won't be any "what kinds of objects?" prompt,
- so no opportunity to answer `m' at that prompt).
+ % Something edible (not necessarily healthy).
- A few other commands (eat food, offer sacrifice, apply tin-
- ning-kit) use the `m' prefix to skip checking for applicable
- objects on the floor and go straight to checking inventory,
- or (for "#loot" to remove a saddle), skip containers and go
- straight to adjacent monsters. The prefix will make "#trav-
- el" command show a menu of interesting targets in sight. In
- debug mode (aka "wizard mode"), the `m' prefix may also be
- used with the "#teleport" and "#wizlevelport" commands.
+ ? A scroll.
- F[yuhjklbn]
- Prefix: fight a monster (even if you only guess one is
- there).
+ / A wand.
- M[yuhjklbn]
- Prefix: move far, no pickup.
+ = A ring.
- g[yuhjklbn]
- Prefix: move until something interesting is found.
+ ! A potion.
- G[yuhjklbn] or [yuhjklbn]
- Prefix: same as `g', but forking of corridors is not con-
- sidered interesting.
+ ( A useful item (pick-axe, key, lamp...).
- _ Travel to a map location via a shortest-path algorithm.
+ " An amulet or a spider web.
- The shortest path is computed over map locations the hero
- knows about (e.g. seen or previously traversed). If there
- is no known path, a guess is made instead. Stops on most of
- the same conditions as the `G' command, but without picking
- up objects, similar to the `M' command. For ports with
- mouse support, the command is also invoked when a mouse-
- click takes place on a location other than the current posi-
- tion.
+ * A gem or rock (possibly valuable, possibly worthless).
- . Wait or rest, do nothing for one turn.
+ ` A boulder or statue.
- a Apply (use) a tool (pick-axe, key, lamp...).
+ 0 An iron ball.
- If used on a wand, that wand will be broken, releasing its
- magic in the process. Confirmation is required.
+ _ An altar, or an iron chain.
- A Remove one or more worn items, such as armor.
+ { A fountain.
- Use `T' (take off) to take off only one piece of armor or
- `R' (remove) to take off only one accessory.
+ } A pool of water or moat or a pool of lava.
+ \ An opulent throne.
+ a-zA-Z and other symbols
+ Letters and certain other symbols represent the various inhabi-
+ tants of the Mazes of Menace. Watch out, they can be nasty and
+ vicious. Sometimes, however, they can be helpful.
+ I This marks the last known location of an invisible or otherwise
+ unseen monster. Note that the monster could have moved. The `F'
+ and `m' commands may be useful here.
- NetHack 3.6 March 4, 2020
+ You need not memorize all these symbols; you can ask the game
+ what any symbol represents with the `/' command (see the next section
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 12
+ NetHack Guidebook 10
- ^A Redo the previous command.
- c Close a door.
- C Call (name) a monster, an individual object, or a type of
- object.
+ for more info).
- Same as extended command "#name".
+ 4. Commands
- ^C Panic button. Quit the game.
+ Commands can be initiated by typing one or two characters to
+ which the command is bound to, or typing the command name in the
+ extended commands entry. Some commands, like "search", do not require
+ that any more information be collected by NetHack. Other commands
+ might require additional information, for example a direction, or an
+ object to be used. For those commands that require additional infor-
+ mation, NetHack will present you with either a menu of choices or with
+ a command line prompt requesting information. Which you are presented
+ with will depend chiefly on how you have set the menustyle option.
- d Drop something.
+ For example, a common question, in the form "What do you want to
+ use? [a-zA-Z ?*]", asks you to choose an object you are carrying.
+ Here, "a-zA-Z" are the inventory letters of your possible choices.
+ Typing `?' gives you an inventory list of these items, so you can see
+ what each letter refers to. In this example, there is also a `*'
+ indicating that you may choose an object not on the list, if you
+ wanted to use something unexpected. Typing a `*' lists your entire
+ inventory, so you can see the inventory letters of every object you're
+ carrying. Finally, if you change your mind and decide you don't want
+ to do this command after all, you can press the ESC key to abort the
+ command.
- For example "d7a" means drop seven items of object a.
+ You can put a number before some commands to repeat them that
+ many times; for example, "10s" will search ten times. If you have the
+ number_pad option set, you must type `n' to prefix a count, so the
+ example above would be typed "n10s" instead. Commands for which
+ counts make no sense ignore them. In addition, movement commands can
+ be prefixed for greater control (see below). To cancel a count or a
+ prefix, press the ESC key.
- D Drop several things.
+ The list of commands is rather long, but it can be read at any
+ time during the game through the `?' command, which accesses a menu of
+ helpful texts. Here are the default key bindings for your reference:
- In answer to the question
+ ? Help menu: display one of several help texts available.
- "What kinds of things do you want to drop? [!%= BUCXaium]"
+ / The "whatis" command, to tell what a symbol represents. You may
+ choose to specify a location or type a symbol (or even a whole
+ word) to explain. Specifying a location is done by moving the
+ cursor to a particular spot on the map and then pressing one of
+ `.', `,', `;', or `:'. `.' will explain the symbol at the chosen
+ location, conditionally check for "More info?" depending upon
+ whether the help option is on, and then you will be asked to pick
+ another location; `,' will explain the symbol but skip any addi-
+ tional information, then let you pick another location; `;' will
+ skip additional info and also not bother asking you to choose
+ another location to examine; `:' will show additional info, if
+ any, without asking for confirmation. When picking a location,
+ pressing the ESC key will terminate this command, or pressing `?'
+ will give a brief reminder about how it works.
- you should type zero or more object symbols possibly fol-
- lowed by `a' and/or `i' and/or `u' and/or `m'. In addition,
- one or more of the blessed/uncursed/cursed groups may be
- typed.
- DB - drop all objects known to be blessed.
- DU - drop all objects known to be uncursed.
- DC - drop all objects known to be cursed.
- DX - drop all objects of unknown B/U/C status.
- Da - drop all objects, without asking for confirmation.
- Di - examine your inventory before dropping anything.
- Du - drop only unpaid objects (when in a shop).
- Dm - use a menu to pick which object(s) to drop.
- D%u - drop only unpaid food.
+ NetHack 3.6.7 February 3, 2023
- The last example shows a combination. There are three cate-
- gories of object filtering: class (`!' for potions, `?' for
- scrolls, and so on), shop status (`u' for unpaid, in other
- words, owned by the shop), and bless/curse state (`B', `U',
- `C', and `X' as shown above). If you specify more than one
- value in a category (such as "!?" for potions and scrolls or
- "BU" for blessed and uncursed), an inventory object will
- meet the criteria if it matches any of the specified values
- (so "!?" means `!' or `?'). If you specify more than one
- category, an inventory object must meet each of the category
- criteria (so "%u" means class `%' and unpaid `u'). Lastly,
- you may specify multiple values within multiple categories:
- "!?BU" will select all potions and scrolls which are known
- to be blessed or uncursed. (In versions prior to 3.6, fil-
- ter combinations behaved differently.)
- ^D Kick something (usually a door).
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 11
+ If the autodescribe option is on, a short description of what you
+ see at each location is shown as you move the cursor. Typing `#'
+ while picking a location will toggle that option on or off. The
+ whatis_coord option controls whether the short description
+ includes map coordinates.
+ Specifying a name rather than a location always gives any addi-
+ tional information available about that name.
- NetHack Guidebook 13
+ You may also request a description of nearby monsters, all mon-
+ sters currently displayed, nearby objects, or all objects. The
+ whatis_coord option controls which format of map coordinate is
+ included with their descriptions.
+ & Tell what a command does.
+ < Go up to the previous level (if you are on a staircase or lad-
+ der).
- e Eat food.
+ > Go down to the next level (if you are on a staircase or ladder).
- Normally checks for edible item(s) on the floor, then if
- none are found or none are chosen, checks for edible item(s)
- in inventory. Precede `e' with the `m' prefix to bypass at-
- tempting to eat anything off the floor.
+ [yuhjklbn]
+ Go one step in the direction indicated (see Figure 2). If you
+ sense or remember a monster there, you will fight the monster
+ instead. Only these one-step movement commands cause you to
+ fight monsters; the others (below) are "safe."
- If you attempt to eat while already satiated, you might
- choke to death. If you risk it, you will be asked whether
- to "continue eating?" if you survive the first bite. You
- can set the paranoid_confirmation:eating option to require a
- response of yes instead of just y.
+ y k u 7 8 9
+ \ | / \ | /
+ h- . -l 4- . -6
+ / | \ / | \
+ b j n 1 2 3
+ (if number_pad is set)
- E Engrave a message on the floor.
+ Figure 2
- E- - write in the dust with your fingers.
+ [YUHJKLBN]
+ Go in that direction until you hit a wall or run into something.
- Engraving the word "Elbereth" will cause most monsters to
- not attack you hand-to-hand (but if you attack, you will rub
- it out); this is often useful to give yourself a breather.
+ m[yuhjklbn]
+ Prefix: move without picking up objects or fighting (even if you
+ remember a monster there).
- f Fire (shoot or throw) one of the objects placed in your
- quiver (or quiver sack, or that you have at the ready). You
- may select ammunition with a previous `Q' command, or let
- the computer pick something appropriate if autoquiver is
- true.
+ A few non-movement commands use the `m' prefix to request operat-
+ ing via menu (to temporarily override the menustyle:Traditional
+ option). Primarily useful for `,' (pickup) when there is only
+ one class of objects present (where there won't be any "what
+ kinds of objects?" prompt, so no opportunity to answer `m' at
+ that prompt).
- See also `t' (throw) for more general throwing and shooting.
+ A few other commands (eat food, offer sacrifice, apply tinning-
+ kit) use the `m' prefix to skip checking for applicable objects
+ on the floor and go straight to checking inventory, or (for
+ "#loot" to remove a saddle), skip containers and go straight to
- i List your inventory (everything you're carrying).
- I List selected parts of your inventory, usually be specifying
- the character for a particular set of objects, like `[' for
- armor or `!' for potions.
+ NetHack 3.6.7 February 3, 2023
- I* - list all gems in inventory;
- Iu - list all unpaid items;
- Ix - list all used up items that are on your shopping bill;
- IB - list all items known to be blessed;
- IU - list all items known to be uncursed;
- IC - list all items known to be cursed;
- IX - list all items whose bless/curse status is unknown;
- I$ - count your money.
- o Open a door.
- O Set options.
- A menu showing the current option values will be displayed.
- You can change most values simply by selecting the menu en-
- try for the given option (ie, by typing its letter or click-
- ing upon it, depending on your user interface). For the
- non-boolean choices, a further menu or prompt will appear
- once you've closed this menu. The available options are
+ NetHack Guidebook 12
- NetHack 3.6 March 4, 2020
+ adjacent monsters. The prefix will make "#travel" command show a
+ menu of interesting targets in sight. In debug mode (aka "wizard
+ mode"), the `m' prefix may also be used with the "#teleport" and
+ "#wizlevelport" commands.
+ F[yuhjklbn]
+ Prefix: fight a monster (even if you only guess one is there).
+ M[yuhjklbn]
+ Prefix: move far, no pickup.
- NetHack Guidebook 14
+ g[yuhjklbn]
+ Prefix: move until something interesting is found.
+ G[yuhjklbn] or [yuhjklbn]
+ Prefix: same as `g', but forking of corridors is not considered
+ interesting.
+ _ Travel to a map location via a shortest-path algorithm.
- listed later in this Guidebook. Options are usually set be-
- fore the game rather than with the `O' command; see the sec-
- tion on options below.
+ The shortest path is computed over map locations the hero knows
+ about (e.g. seen or previously traversed). If there is no known
+ path, a guess is made instead. Stops on most of the same condi-
+ tions as the `G' command, but without picking up objects, similar
+ to the `M' command. For ports with mouse support, the command is
+ also invoked when a mouse-click takes place on a location other
+ than the current position.
- ^O Show overview.
+ . Wait or rest, do nothing for one turn.
- Shortcut for "#overview": list interesting dungeon levels
- visited.
+ a Apply (use) a tool (pick-axe, key, lamp...).
- (Prior to 3.6.0, `^O' was a debug mode command which listed
- the placement of all special levels. Use "#wizwhere" to run
- that command.)
+ If used on a wand, that wand will be broken, releasing its magic
+ in the process. Confirmation is required.
- p Pay your shopping bill.
+ A Remove one or more worn items, such as armor.
- P Put on an accessory (ring, amulet, or blindfold).
+ Use `T' (take off) to take off only one piece of armor or `R'
+ (remove) to take off only one accessory.
- This command may also be used to wear armor. The prompt for
- which inventory item to use will only list accessories, but
- choosing an unlisted item of armor will attempt to wear it.
- (See the `W' command below. It lists armor as the inventory
- choices but will accept an accessory and attempt to put that
- on.)
+ ^A Redo the previous command.
- ^P Repeat previous message.
+ c Close a door.
- Subsequent `^P's repeat earlier messages. For some inter-
- faces, the behavior can be varied via the msg_window option.
+ C Call (name) a monster, an individual object, or a type of object.
- q Quaff (drink) something (potion, water, etc).
+ Same as extended command "#name".
- Q Select an object for your quiver, quiver sack, or just gen-
- erally at the ready (only one of these is available at a
- time). You can then throw this (or one of these) using the
- `f' command.
+ ^C Panic button. Quit the game.
- (In versions prior to 3.3 this was the command to quit the
- game, which has been moved to "#quit".)
+ d Drop something.
- r Read a scroll or spellbook.
+ For example "d7a" means drop seven items of object a.
- R Remove a worn accessory (ring, amulet, or blindfold).
- If you're wearing more than one, you'll be prompted for
- which one to remove. When you're only wearing one, then by
- default it will be removed without asking, but you can set
- the paranoid_confirmation option to require a prompt.
- This command may also be used to take off armor. The prompt
- for which inventory item to remove only lists worn acces-
- sories, but an item of worn armor can be chosen. (See the
- `T' command below. It lists armor as the inventory choices
- but will accept an accessory and attempt to remove it.)
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 13
- NetHack Guidebook 15
+ D Drop several things.
+ In answer to the question
+ "What kinds of things do you want to drop? [!%= BUCXaium]"
- ^R Redraw the screen.
+ you should type zero or more object symbols possibly followed by
+ `a' and/or `i' and/or `u' and/or `m'. In addition, one or more
+ of the blessed/uncursed/cursed groups may be typed.
- s Search for secret doors and traps around you. It usually
- takes several tries to find something.
+ DB - drop all objects known to be blessed.
+ DU - drop all objects known to be uncursed.
+ DC - drop all objects known to be cursed.
+ DX - drop all objects of unknown B/U/C status.
+ Da - drop all objects, without asking for confirmation.
+ Di - examine your inventory before dropping anything.
+ Du - drop only unpaid objects (when in a shop).
+ Dm - use a menu to pick which object(s) to drop.
+ D%u - drop only unpaid food.
- Can also be used to figure out whether there is still a mon-
- ster at an adjacent "remembered, unseen monster" marker.
+ The last example shows a combination. There are three categories
+ of object filtering: class (`!' for potions, `?' for scrolls, and
+ so on), shop status (`u' for unpaid, in other words, owned by the
+ shop), and bless/curse state (`B', `U', `C', and `X' as shown
+ above). If you specify more than one value in a category (such
+ as "!?" for potions and scrolls or "BU" for blessed and
+ uncursed), an inventory object will meet the criteria if it
+ matches any of the specified values (so "!?" means `!' or `?').
+ If you specify more than one category, an inventory object must
+ meet each of the category criteria (so "%u" means class `%' and
+ unpaid `u'). Lastly, you may specify multiple values within mul-
+ tiple categories: "!?BU" will select all potions and scrolls
+ which are known to be blessed or uncursed. (In versions prior to
+ 3.6, filter combinations behaved differently.)
- S Save the game (which suspends play and exits the program).
- The saved game will be restored automatically the next time
- you play using the same character name.
+ ^D Kick something (usually a door).
- In normal play, once a saved game is restored the file used
- to hold the saved data is deleted. In explore mode, once
- restoration is accomplished you are asked whether to keep or
- delete the file. Keeping the file makes it feasible to play
- for a while then quit without saving and later restore
- again.
+ e Eat food.
- There is no "save current game state and keep playing" com-
- mand, not even in explore mode where saved game files can be
- kept and re-used.
+ Normally checks for edible item(s) on the floor, then if none are
+ found or none are chosen, checks for edible item(s) in inventory.
+ Precede `e' with the `m' prefix to bypass attempting to eat any-
+ thing off the floor.
- t Throw an object or shoot a projectile.
+ If you attempt to eat while already satiated, you might choke to
+ death. If you risk it, you will be asked whether to "continue
+ eating?" if you survive the first bite. You can set the para-
+ noid_confirmation:eating option to require a response of yes
+ instead of just y.
- There's no separate "shoot" command. If you throw an arrow
- while wielding a bow, you are shooting that arrow and any
- weapon skill bonus or penalty for bow applies. If you throw
- an arrow while not wielding a bow, you are throwing it by
- hand and it will generally be less effective than when shot.
+ E Engrave a message on the floor.
- See also `f' (fire) for throwing or shooting an item pre-se-
- lected via the `Q' (quiver) command.
+ E- - write in the dust with your fingers.
- T Take off armor.
- If you're wearing more than one piece, you'll be prompted
- for which one to take off. (Note that this treats a cloak
- covering a suit and/or a shirt, or a suit covering a shirt,
- as if the underlying items weren't there.) When you're only
- wearing one, then by default it will be taken off without
- asking, but you can set the paranoid_confirmation option to
- require a prompt.
- This command may also be used to remove accessories. The
- prompt for which inventory item to take off only lists worn
- armor, but a worn accessory can be chosen. (See the `R'
- command above. It lists accessories as the inventory choic-
- es but will accept an item of armor and attempt to take it
- off.)
+ NetHack 3.6.7 February 3, 2023
- ^T Teleport, if you have the ability.
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 14
+ Engraving the word "Elbereth" will cause most monsters to not
+ attack you hand-to-hand (but if you attack, you will rub it out);
+ this is often useful to give yourself a breather.
+ f Fire (shoot or throw) one of the objects placed in your quiver
+ (or quiver sack, or that you have at the ready). You may select
+ ammunition with a previous `Q' command, or let the computer pick
+ something appropriate if autoquiver is true.
- NetHack Guidebook 16
+ See also `t' (throw) for more general throwing and shooting.
+ i List your inventory (everything you're carrying).
+ I List selected parts of your inventory, usually be specifying the
+ character for a particular set of objects, like `[' for armor or
+ `!' for potions.
- v Display version number.
+ I* - list all gems in inventory;
+ Iu - list all unpaid items;
+ Ix - list all used up items that are on your shopping bill;
+ IB - list all items known to be blessed;
+ IU - list all items known to be uncursed;
+ IC - list all items known to be cursed;
+ IX - list all items whose bless/curse status is unknown;
+ I$ - count your money.
- V Display the game history.
+ o Open a door.
- w Wield weapon.
+ O Set options.
- w- - wield nothing, use your bare (or gloved) hands.
+ A menu showing the current option values will be displayed. You
+ can change most values simply by selecting the menu entry for the
+ given option (ie, by typing its letter or clicking upon it,
+ depending on your user interface). For the non-boolean choices,
+ a further menu or prompt will appear once you've closed this
+ menu. The available options are listed later in this Guidebook.
+ Options are usually set before the game rather than with the `O'
+ command; see the section on options below.
- Some characters can wield two weapons at once; use the `X'
- command (or the "#twoweapon" extended command) to do so.
+ ^O Show overview.
- W Wear armor.
+ Shortcut for "#overview": list interesting dungeon levels vis-
+ ited.
- This command may also be used to put on an accessory (ring,
- amulet, or blindfold). The prompt for which inventory item
- to use will only list armor, but choosing an unlisted acces-
- sory will attempt to put it on. (See the `P' command above.
- It lists accessories as the inventory choices but will ac-
- cept an item of armor and attempt to wear it.)
+ (Prior to 3.6.0, `^O' was a debug mode command which listed the
+ placement of all special levels. Use "#wizwhere" to run that
+ command.)
- x Exchange your wielded weapon with the item in your alternate
- weapon slot.
+ p Pay your shopping bill.
- The latter is used as your secondary weapon when engaging in
- two-weapon combat. Note that if one of these slots is emp-
- ty, the exchange still takes place.
+ P Put on an accessory (ring, amulet, or blindfold).
- X Toggle two-weapon combat, if your character can do it. Also
- available via the "#twoweapon" extended command.
+ This command may also be used to wear armor. The prompt for
+ which inventory item to use will only list accessories, but
- (In versions prior to 3.6 this was the command to switch
- from normal play to "explore mode", also known as "discovery
- mode", which has now been moved to "#exploremode".)
- ^X Display basic information about your character.
+ NetHack 3.6.7 February 3, 2023
- Displays name, role, race, gender (unless role name makes
- that redundant, such as Caveman or Priestess), and align-
- ment, along with your patron deity and his or her opposi-
- tion. It also shows most of the various items of informa-
- tion from the status line(s) in a less terse form, including
- several additional things which don't appear in the normal
- status display due to space considerations.
- In normal play, that's all that `^X' displays. In explore
- mode, the role and status feedback is augmented by the in-
- formation provided by enlightenment magic.
- z Zap a wand.
- z. - to aim at yourself, use `.' for the direction.
- Z Zap (cast) a spell.
+ NetHack Guidebook 15
- NetHack 3.6 March 4, 2020
+ choosing an unlisted item of armor will attempt to wear it. (See
+ the `W' command below. It lists armor as the inventory choices
+ but will accept an accessory and attempt to put that on.)
+ ^P Repeat previous message.
+ Subsequent `^P's repeat earlier messages. For some interfaces,
+ the behavior can be varied via the msg_window option.
+ q Quaff (drink) something (potion, water, etc).
+ Q Select an object for your quiver, quiver sack, or just generally
+ at the ready (only one of these is available at a time). You can
+ then throw this (or one of these) using the `f' command.
- NetHack Guidebook 17
+ (In versions prior to 3.3 this was the command to quit the game,
+ which has been moved to "#quit".)
+ r Read a scroll or spellbook.
+ R Remove a worn accessory (ring, amulet, or blindfold).
- Z. - to cast at yourself, use `.' for the direction.
+ If you're wearing more than one, you'll be prompted for which one
+ to remove. When you're only wearing one, then by default it will
+ be removed without asking, but you can set the paranoid_confirma-
+ tion option to require a prompt.
- ^Z Suspend the game (UNIX(R) versions with job control only).
+ This command may also be used to take off armor. The prompt for
+ which inventory item to remove only lists worn accessories, but
+ an item of worn armor can be chosen. (See the `T' command below.
+ It lists armor as the inventory choices but will accept an acces-
+ sory and attempt to remove it.)
- : Look at what is here.
+ ^R Redraw the screen.
- ; Show what type of thing a visible symbol corresponds to.
+ s Search for secret doors and traps around you. It usually takes
+ several tries to find something.
- , Pick up some things from the floor beneath you.
+ Can also be used to figure out whether there is still a monster
+ at an adjacent "remembered, unseen monster" marker.
- May be preceded by `m' to force a selection menu.
+ S Save the game (which suspends play and exits the program). The
+ saved game will be restored automatically the next time you play
+ using the same character name.
- @ Toggle the autopickup option on and off.
+ In normal play, once a saved game is restored the file used to
+ hold the saved data is deleted. In explore mode, once restora-
+ tion is accomplished you are asked whether to keep or delete the
+ file. Keeping the file makes it feasible to play for a while
+ then quit without saving and later restore again.
- ^ Ask for the type of an adjacent trap you found earlier.
+ There is no "save current game state and keep playing" command,
+ not even in explore mode where saved game files can be kept and
+ re-used.
- ) Tell what weapon you are wielding.
- [ Tell what armor you are wearing.
+ NetHack 3.6.7 February 3, 2023
- = Tell what rings you are wearing.
- " Tell what amulet you are wearing.
- ( Tell what tools you are using.
- * Tell what equipment you are using.
- Combines the preceding five type-specific commands into one.
+ NetHack Guidebook 16
- $ Count your gold pieces.
- + List the spells you know.
- Using this command, you can also rearrange the order in
- which your spells are listed, either by sorting the entire
- list or by picking one spell from the menu then picking an-
- other to swap places with it. Swapping pairs of spells
- changes their casting letters, so the change lasts after the
- current `+' command finishes. Sorting the whole list is
- temporary. To make the most recent sort order persist be-
- yond the current `+' command, choose the sort option again
- and then pick "reassign casting letters". (Any spells
- learned after that will be added to the end of the list
- rather than be inserted into the sorted ordering.)
+ t Throw an object or shoot a projectile.
- \ Show what types of objects have been discovered.
+ There's no separate "shoot" command. If you throw an arrow while
+ wielding a bow, you are shooting that arrow and any weapon skill
+ bonus or penalty for bow applies. If you throw an arrow while
+ not wielding a bow, you are throwing it by hand and it will gen-
+ erally be less effective than when shot.
- ` Show discovered types for one class of objects.
+ See also `f' (fire) for throwing or shooting an item pre-selected
+ via the `Q' (quiver) command.
+ T Take off armor.
+ If you're wearing more than one piece, you'll be prompted for
+ which one to take off. (Note that this treats a cloak covering a
+ suit and/or a shirt, or a suit covering a shirt, as if the under-
+ lying items weren't there.) When you're only wearing one, then
+ by default it will be taken off without asking, but you can set
+ the paranoid_confirmation option to require a prompt.
- __________
- (R)UNIX is a registered trademark of The Open Group.
+ This command may also be used to remove accessories. The prompt
+ for which inventory item to take off only lists worn armor, but a
+ worn accessory can be chosen. (See the `R' command above. It
+ lists accessories as the inventory choices but will accept an
+ item of armor and attempt to take it off.)
+ ^T Teleport, if you have the ability.
- NetHack 3.6 March 4, 2020
+ v Display version number.
+ V Display the game history.
+ w Wield weapon.
+ w- - wield nothing, use your bare (or gloved) hands.
+ Some characters can wield two weapons at once; use the `X' com-
+ mand (or the "#twoweapon" extended command) to do so.
- NetHack Guidebook 18
+ W Wear armor.
+ This command may also be used to put on an accessory (ring,
+ amulet, or blindfold). The prompt for which inventory item to
+ use will only list armor, but choosing an unlisted accessory will
+ attempt to put it on. (See the `P' command above. It lists
+ accessories as the inventory choices but will accept an item of
+ armor and attempt to wear it.)
+ x Exchange your wielded weapon with the item in your alternate
+ weapon slot.
- ! Escape to a shell.
+ The latter is used as your secondary weapon when engaging in two-
+ weapon combat. Note that if one of these slots is empty, the
+ exchange still takes place.
- # Perform an extended command.
+ NetHack 3.6.7 February 3, 2023
- As you can see, the authors of NetHack used up all the let-
- ters, so this is a way to introduce the less frequently used com-
- mands. What extended commands are available depends on what fea-
- tures the game was compiled with.
- #adjust
- Adjust inventory letters (most useful when the fixinv option
- is "on"). Autocompletes. Default key is `M-a'.
- This command allows you to move an item from one particular
- inventory slot to another so that it has a letter which is
- more meaningful for you or that it will appear in a particu-
- lar location when inventory listings are displayed. You can
- move to a currently empty slot, or if the destination is oc-
- cupied -- and won't merge -- the item there will swap slots
- with the one being moved. "#adjust" can also be used to
- split a stack of objects; when choosing the item to adjust,
- enter a count prior to its letter.
- Adjusting without a count used to collect all compatible
- stacks when moving to the destination. That behavior has
- been changed; to gather compatible stacks, "#adjust" a stack
- into its own inventory slot. If it has a name assigned,
- other stacks with the same name or with no name will merge
- provided that all their other attributes match. If it does
- not have a name, only other stacks with no name are eligi-
- ble. In either case, otherwise compatible stacks with a
- different name will not be merged. This contrasts with us-
- ing "#adjust" to move from one slot to a different slot. In
- that situation, moving (no count given) a compatible stack
- will merge if either stack has a name when the other doesn't
- and give that name to the result, while splitting (count
- given) will ignore the source stack's name when deciding
- whether to merge with the destination stack.
+ NetHack Guidebook 17
- #annotate
- Allows you to specify one line of text to associate with the
- current dungeon level. All levels with annotations are dis-
- played by the "#overview" command. Autocompletes. Default
- key is `M-A', and also `^N' if number_pad is on.
- #apply
- Apply (use) a tool such as a pick-axe, a key, or a lamp.
- Default key is `a'.
- If the tool used acts on items on the floor, using the `m'
- prefix skips those items.
+ X Toggle two-weapon combat, if your character can do it. Also
+ available via the "#twoweapon" extended command.
+ (In versions prior to 3.6 this was the command to switch from
+ normal play to "explore mode", also known as "discovery mode",
+ which has now been moved to "#exploremode".)
+ ^X Display basic information about your character.
- NetHack 3.6 March 4, 2020
+ Displays name, role, race, gender (unless role name makes that
+ redundant, such as Caveman or Priestess), and alignment, along
+ with your patron deity and his or her opposition. It also shows
+ most of the various items of information from the status line(s)
+ in a less terse form, including several additional things which
+ don't appear in the normal status display due to space considera-
+ tions.
+ In normal play, that's all that `^X' displays. In explore mode,
+ the role and status feedback is augmented by the information pro-
+ vided by enlightenment magic.
+ z Zap a wand.
+ z. - to aim at yourself, use `.' for the direction.
+ Z Zap (cast) a spell.
- NetHack Guidebook 19
+ Z. - to cast at yourself, use `.' for the direction.
+ ^Z Suspend the game (UNIX(R) versions with job control only).
+ : Look at what is here.
- If used on a wand, that wand will be broken, releasing its
- magic in the process. Confirmation is required.
+ ; Show what type of thing a visible symbol corresponds to.
- #attributes
- Show your attributes. Default key is `^X'.
+ , Pick up some things from the floor beneath you.
- #autopickup
- Toggle the autopickup option on/off. Default key is `@'.
+ May be preceded by `m' to force a selection menu.
- #call
- Call (name) a monster, or an object in inventory, on the
- floor, or in the discoveries list, or add an annotation for
- the current level (same as "#annotate"). Default key is
- `C'.
+ @ Toggle the autopickup option on and off.
- #cast
- Cast a spell. Default key is `Z'.
+ ^ Ask for the type of an adjacent trap you found earlier.
- #chat
- Talk to someone. Default key is `M-c'.
+ ) Tell what weapon you are wielding.
- #close
- Close a door. Default key is `c'.
+ [ Tell what armor you are wearing.
- #conduct
- List voluntary challenges you have maintained. Autocom-
- pletes. Default key is `M-C'.
+ = Tell what rings you are wearing.
- See the section below entitled "Conduct" for details.
+ " Tell what amulet you are wearing.
- #dip
- Dip an object into something. Autocompletes. Default key
- is `M-d'.
- #down
- Go down a staircase. Default key is `>'.
+ __________
+ (R)UNIX is a registered trademark of The Open Group.
- #drop
- Drop an item. Default key is `d'.
- #droptype
- Drop specific item types. Default key is `D'.
+ NetHack 3.6.7 February 3, 2023
- #eat
- Eat something. Default key is `e'. The `m' prefix skips
- eating items on the floor.
- #engrave
- Engrave writing on the floor. Default key is `E'.
- #enhance
- Advance or check weapon and spell skills. Autocompletes.
- Default key is `M-e'.
+ NetHack Guidebook 18
- NetHack 3.6 March 4, 2020
+ ( Tell what tools you are using.
+ * Tell what equipment you are using.
+ Combines the preceding five type-specific commands into one.
- NetHack Guidebook 20
+ $ Count your gold pieces.
+ + List the spells you know.
+ Using this command, you can also rearrange the order in which
+ your spells are listed, either by sorting the entire list or by
+ picking one spell from the menu then picking another to swap
+ places with it. Swapping pairs of spells changes their casting
+ letters, so the change lasts after the current `+' command fin-
+ ishes. Sorting the whole list is temporary. To make the most
+ recent sort order persist beyond the current `+' command, choose
+ the sort option again and then pick "reassign casting letters".
+ (Any spells learned after that will be added to the end of the
+ list rather than be inserted into the sorted ordering.)
- #exploremode
- Enter the explore mode.
+ \ Show what types of objects have been discovered.
- Requires confirmation; default response is n (no). To real-
- ly switch to explore mode, respond with y. You can set the
- paranoid_confirmation:quit option to require a response of
- yes instead.
+ ` Show discovered types for one class of objects.
- #fire
- Fire ammunition from quiver. Default key is `f'.
+ ! Escape to a shell.
- #force
- Force a lock. Autocompletes. Default key is `M-f'.
+ # Perform an extended command.
- #glance
- Show what type of thing a map symbol corresponds to. De-
- fault key is `;'.
- #help
- Show the help menu. Default key is `?', and also `h' if
- number_pad is on.
- #herecmdmenu
- Show a menu of possible actions in your current location.
+ As you can see, the authors of NetHack used up all the letters,
+ so this is a way to introduce the less frequently used commands. What
+ extended commands are available depends on what features the game was
+ compiled with.
- #history
- Show long version and game history. Default key is `V'.
+ #adjust
+ Adjust inventory letters (most useful when the fixinv option is
+ "on"). Autocompletes. Default key is `M-a'.
- #inventory
- Show your inventory. Default key is `i'.
+ This command allows you to move an item from one particular
+ inventory slot to another so that it has a letter which is more
+ meaningful for you or that it will appear in a particular loca-
+ tion when inventory listings are displayed. You can move to a
+ currently empty slot, or if the destination is occupied -- and
+ won't merge -- the item there will swap slots with the one being
+ moved. "#adjust" can also be used to split a stack of objects;
+ when choosing the item to adjust, enter a count prior to its let-
+ ter.
- #inventtype
- Inventory specific item types. Default key is `I'.
+ Adjusting without a count used to collect all compatible stacks
+ when moving to the destination. That behavior has been changed;
+ to gather compatible stacks, "#adjust" a stack into its own
+ inventory slot. If it has a name assigned, other stacks with the
- #invoke
- Invoke an object's special powers. Autocompletes. Default
- key is `M-i'.
- #jump
- Jump to another location. Autocompletes. Default key is
- `M-j', and also `j' if number_pad is on.
+ NetHack 3.6.7 February 3, 2023
- #kick
- Kick something. Default key is `^D', and `k' if number_pad
- is on.
- #known
- Show what object types have been discovered. Default key is
- `\'.
- #knownclass
- Show discovered types for one class of objects. Default key
- is ``'.
+ NetHack Guidebook 19
- NetHack 3.6 March 4, 2020
+ same name or with no name will merge provided that all their
+ other attributes match. If it does not have a name, only other
+ stacks with no name are eligible. In either case, otherwise com-
+ patible stacks with a different name will not be merged. This
+ contrasts with using "#adjust" to move from one slot to a differ-
+ ent slot. In that situation, moving (no count given) a compati-
+ ble stack will merge if either stack has a name when the other
+ doesn't and give that name to the result, while splitting (count
+ given) will ignore the source stack's name when deciding whether
+ to merge with the destination stack.
+ #annotate
+ Allows you to specify one line of text to associate with the cur-
+ rent dungeon level. All levels with annotations are displayed by
+ the "#overview" command. Autocompletes. Default key is `M-A',
+ and also `^N' if number_pad is on.
+ #apply
+ Apply (use) a tool such as a pick-axe, a key, or a lamp. Default
+ key is `a'.
- NetHack Guidebook 21
+ If the tool used acts on items on the floor, using the `m' prefix
+ skips those items.
+ If used on a wand, that wand will be broken, releasing its magic
+ in the process. Confirmation is required.
+ #attributes
+ Show your attributes. Default key is `^X'.
- #levelchange
- Change your experience level. Autocompletes. Debug mode
- only.
+ #autopickup
+ Toggle the autopickup option on/off. Default key is `@'.
- #lightsources
- Show mobile light sources. Autocompletes. Debug mode only.
+ #call
+ Call (name) a monster, or an object in inventory, on the floor,
+ or in the discoveries list, or add an annotation for the current
+ level (same as "#annotate"). Default key is `C'.
- #look
- Look at what is here, under you. Default key is `:'.
+ #cast
+ Cast a spell. Default key is `Z'.
- #loot
- Loot a box or bag on the floor beneath you, or the saddle
- from a steed standing next to you. Autocompletes. Precede
- with the `m' prefix to skip containers at your location and
- go directly to removing a saddle. Default key is `M-l', and
- also `l' if number_pad is on.
+ #chat
+ Talk to someone. Default key is `M-c'.
- #monster
- Use a monster's special ability (when polymorphed into mon-
- ster form). Autocompletes. Default key is `M-m'.
+ #close
+ Close a door. Default key is `c'.
- #name
- Name a monster, an individual object, or a type of object.
- Same as "#call". Autocompletes. Default keys are `N', `M-
- n', and `M-N'.
+ #conduct
+ List voluntary challenges you have maintained. Autocompletes.
+ Default key is `M-C'.
- #offer
- Offer a sacrifice to the gods. Autocompletes. Default key
- is `M-o'.
+ See the section below entitled "Conduct" for details.
- You'll need to find an altar to have any chance at success.
- Corpses of recently killed monsters are the fodder of
- choice.
- The `m' prefix skips offering any items which are on the al-
- tar.
- #open
- Open a door. Default key is `o'.
- #options
- Show and change option settings. Default key is `O'.
+ NetHack 3.6.7 February 3, 2023
- #overview
- Display information you've discovered about the dungeon.
- Any visited level (unless forgotten due to amnesia) with an
- annotation is included, and many things (altars, thrones,
- fountains, and so on; extra stairs leading to another dun-
- geon branch) trigger an automatic annotation. If dungeon
- overview is chosen during end-of-game disclosure, every vis-
- ited level will be included regardless of annotations. Au-
- tocompletes. Default keys are `^O', and `M-O'.
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 20
+ #dip
+ Dip an object into something. Autocompletes. Default key is `M-
+ d'.
+ #down
+ Go down a staircase. Default key is `>'.
- NetHack Guidebook 22
+ #drop
+ Drop an item. Default key is `d'.
+ #droptype
+ Drop specific item types. Default key is `D'.
+ #eat
+ Eat something. Default key is `e'. The `m' prefix skips eating
+ items on the floor.
- #panic
- Test the panic routine. Terminates the current game. Auto-
- completes. Debug mode only.
+ #engrave
+ Engrave writing on the floor. Default key is `E'.
- Asks for confirmation; default is n (no); continue playing.
- To really panic, respond with y. You can set the para-
- noid_confirmation:quit option to require a response of yes
- instead.
+ #enhance
+ Advance or check weapon and spell skills. Autocompletes.
+ Default key is `M-e'.
- #pay
- Pay your shopping bill. Default key is `p'.
+ #exploremode
+ Enter the explore mode.
- #pickup
- Pick up things at the current location. Default key is `,'.
- The `m' prefix forces use of a menu.
+ Requires confirmation; default response is n (no). To really
+ switch to explore mode, respond with y. You can set the para-
+ noid_confirmation:quit option to require a response of yes
+ instead.
- #polyself
- Polymorph self. Autocompletes. Debug mode only.
+ #fire
+ Fire ammunition from quiver. Default key is `f'.
- #pray
- Pray to the gods for help. Autocompletes. Default key is
- `M-p'.
+ #force
+ Force a lock. Autocompletes. Default key is `M-f'.
- Praying too soon after receiving prior help is a bad idea.
- (Hint: entering the dungeon alive is treated as having re-
- ceived help. You probably shouldn't start off a new game by
- praying right away.) Since using this command by accident
- can cause trouble, there is an option to make you confirm
- your intent before praying. It is enabled by default, and
- you can reset the paranoid_confirmation option to disable
- it.
+ #glance
+ Show what type of thing a map symbol corresponds to. Default key
+ is `;'.
- #prevmsg
- Show previously displayed game messages. Default key is
- `^P'.
+ #help
+ Show the help menu. Default key is `?', and also `h' if num-
+ ber_pad is on.
- #puton
- Put on an accessory (ring, amulet, etc). Default key is
- `P'.
+ #herecmdmenu
+ Show a menu of possible actions in your current location.
- #quaff
- Quaff (drink) something. Default key is `q'.
+ #history
+ Show long version and game history. Default key is `V'.
- #quit
- Quit the program without saving your game. Autocompletes.
- Default key is `M-q'.
+ #inventory
+ Show your inventory. Default key is `i'.
- Since using this command by accident would throw away the
- current game, you are asked to confirm your intent before
- quitting. Default response is n (no); continue playing. To
- really quit, respond with y. You can set the paranoid_con-
- firmation:quit option to require a response of yes instead.
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 21
- NetHack Guidebook 23
+ #inventtype
+ Inventory specific item types. Default key is `I'.
+ #invoke
+ Invoke an object's special powers. Autocompletes. Default key
+ is `M-i'.
+ #jump
+ Jump to another location. Autocompletes. Default key is `M-j',
+ and also `j' if number_pad is on.
- #quiver
- Select ammunition for quiver. Default key is `Q'.
+ #kick
+ Kick something. Default key is `^D', and `k' if number_pad is
+ on.
- #read
- Read a scroll, a spellbook, or something else. Default key
- is `r'.
+ #known
+ Show what object types have been discovered. Default key is `\'.
- #redraw
- Redraw the screen. Default key is `^R', and also `^L' if
- number_pad is on.
+ #knownclass
+ Show discovered types for one class of objects. Default key is
+ ``'.
- #remove
- Remove an accessory (ring, amulet, etc). Default key is
- `R'.
+ #levelchange
+ Change your experience level. Autocompletes. Debug mode only.
- #ride
- Ride (or stop riding) a saddled creature. Autocompletes.
- Default key is `M-R'.
+ #lightsources
+ Show mobile light sources. Autocompletes. Debug mode only.
- #rub
- Rub a lamp or a stone. Autocompletes. Default key is `M-
- r'.
+ #look
+ Look at what is here, under you. Default key is `:'.
- #save
- Save the game and exit the program. Default key is `S'.
+ #loot
+ Loot a box or bag on the floor beneath you, or the saddle from a
+ steed standing next to you. Autocompletes. Precede with the `m'
+ prefix to skip containers at your location and go directly to
+ removing a saddle. Default key is `M-l', and also `l' if num-
+ ber_pad is on.
- #search
- Search for traps and secret doors around you. Default key
- is `s'.
+ #monster
+ Use a monster's special ability (when polymorphed into monster
+ form). Autocompletes. Default key is `M-m'.
- #seeall
- Show all equipment in use. Default key is `*'.
+ #name
+ Name a monster, an individual object, or a type of object. Same
+ as "#call". Autocompletes. Default keys are `N', `M-n', and `M-
+ N'.
- #seeamulet
- Show the amulet currently worn. Default key is `"'.
+ #offer
+ Offer a sacrifice to the gods. Autocompletes. Default key is
+ `M-o'.
- #seearmor
- Show the armor currently worn. Default key is `['.
+ You'll need to find an altar to have any chance at success.
+ Corpses of recently killed monsters are the fodder of choice.
- #seegold
- Count your gold. Default key is `$'.
- #seenv
- Show seen vectors. Autocompletes. Debug mode only.
- #seerings
- Show the ring(s) currently worn. Default key is `='.
+ NetHack 3.6.7 February 3, 2023
- #seespells
- List and reorder known spells. Default key is `+'.
- #seetools
- Show the tools currently in use. Default key is `('.
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 22
+ The `m' prefix skips offering any items which are on the altar.
+ #open
+ Open a door. Default key is `o'.
- NetHack Guidebook 24
+ #options
+ Show and change option settings. Default key is `O'.
+ #overview
+ Display information you've discovered about the dungeon. Any
+ visited level (unless forgotten due to amnesia) with an annota-
+ tion is included, and many things (altars, thrones, fountains,
+ and so on; extra stairs leading to another dungeon branch) trig-
+ ger an automatic annotation. If dungeon overview is chosen dur-
+ ing end-of-game disclosure, every visited level will be included
+ regardless of annotations. Autocompletes. Default keys are
+ `^O', and `M-O'.
+ #panic
+ Test the panic routine. Terminates the current game. Autocom-
+ pletes. Debug mode only.
- #seetrap
- Show the type of an adjacent trap. Default key is `^'.
+ Asks for confirmation; default is n (no); continue playing. To
+ really panic, respond with y. You can set the paranoid_confirma-
+ tion:quit option to require a response of yes instead.
- #seeweapon
- Show the weapon currently wielded. Default key is `)'.
+ #pay
+ Pay your shopping bill. Default key is `p'.
- #shell
- Do a shell escape. Default key is `!'.
+ #pickup
+ Pick up things at the current location. Default key is `,'. The
+ `m' prefix forces use of a menu.
- #sit
- Sit down. Autocompletes. Default key is `M-s'.
+ #polyself
+ Polymorph self. Autocompletes. Debug mode only.
- #stats
- Show memory usage statistics. Autocompletes. Debug mode
- only.
+ #pray
+ Pray to the gods for help. Autocompletes. Default key is `M-p'.
- #suspend
- Suspend the game. Default key is `^Z'.
+ Praying too soon after receiving prior help is a bad idea.
+ (Hint: entering the dungeon alive is treated as having received
+ help. You probably shouldn't start off a new game by praying
+ right away.) Since using this command by accident can cause
+ trouble, there is an option to make you confirm your intent
+ before praying. It is enabled by default, and you can reset the
+ paranoid_confirmation option to disable it.
- #swap
- Swap wielded and secondary weapons. Default key is `x'.
+ #prevmsg
+ Show previously displayed game messages. Default key is `^P'.
- #takeoff
- Take off one piece of armor. Default key is `T'.
+ #puton
+ Put on an accessory (ring, amulet, etc). Default key is `P'.
- #takeoffall
- Remove all armor. Default key is `A'.
- #teleport
- Teleport around the level. Default key is `^T'.
- #terrain
- Show bare map without displaying monsters, objects, or
- traps. Autocompletes.
- #therecmdmenu
- Show a menu of possible actions in a location next to you.
+ NetHack 3.6.7 February 3, 2023
- #throw
- Throw something. Default key is `t'.
- #timeout
- Look at the timeout queue. Autocompletes. Debug mode only.
- #tip
- Tip over a container (bag or box) to pour out its contents.
- Autocompletes. Default key is `M-T'. The `m' prefix makes
- the command use a menu.
- #travel
- Travel to a specific location on the map. Default key is
- `_'. Using the "request menu" prefix shows a menu of inter-
- esting targets in sight without asking to move the cursor.
- When picking a target with cursor and the autodescribe
+ NetHack Guidebook 23
- NetHack 3.6 March 4, 2020
+ #quaff
+ Quaff (drink) something. Default key is `q'.
+ #quit
+ Quit the program without saving your game. Autocompletes.
+ Default key is `M-q'.
+ Since using this command by accident would throw away the current
+ game, you are asked to confirm your intent before quitting.
+ Default response is n (no); continue playing. To really quit,
+ respond with y. You can set the paranoid_confirmation:quit
+ option to require a response of yes instead.
- NetHack Guidebook 25
+ #quiver
+ Select ammunition for quiver. Default key is `Q'.
+ #read
+ Read a scroll, a spellbook, or something else. Default key is
+ `r'.
+ #redraw
+ Redraw the screen. Default key is `^R', and also `^L' if num-
+ ber_pad is on.
- option is on, the top line will show "(no travel path)" if
- your character does not know of a path to that location.
+ #remove
+ Remove an accessory (ring, amulet, etc). Default key is `R'.
- #turn
- Turn undead away. Autocompletes. Default key is `M-t'.
+ #ride
+ Ride (or stop riding) a saddled creature. Autocompletes.
+ Default key is `M-R'.
- #twoweapon
- Toggle two-weapon combat on or off. Autocompletes. Default
- key is `X', and also `M-2' if number_pad is off.
+ #rub
+ Rub a lamp or a stone. Autocompletes. Default key is `M-r'.
- Note that you must use suitable weapons for this type of
- combat, or it will be automatically turned off.
+ #save
+ Save the game and exit the program. Default key is `S'.
- #untrap
- Untrap something (trap, door, or chest). Default key is `M-
- u', and `u' if number_pad is on.
+ #search
+ Search for traps and secret doors around you. Default key is
+ `s'.
- In some circumstances it can also be used to rescue trapped
- monsters.
+ #seeall
+ Show all equipment in use. Default key is `*'.
- #up
- Go up a staircase. Default key is `<'.
+ #seeamulet
+ Show the amulet currently worn. Default key is `"'.
- #vanquished
- List vanquished monsters. Autocompletes. Debug mode only.
+ #seearmor
+ Show the armor currently worn. Default key is `['.
- #version
- Print compile time options for this version of NetHack. Au-
- tocompletes. Default key is `M-v'.
+ #seegold
+ Count your gold. Default key is `$'.
- #versionshort
- Show version string. Default key is `v'.
- #vision
- Show vision array. Autocompletes. Debug mode only.
- #wait
- Rest one move while doing nothing. Default key is `.', and
- also ` ' if rest_on_space is on.
- #wear
- Wear a piece of armor. Default key is `W'.
+ NetHack 3.6.7 February 3, 2023
- #whatdoes
- Tell what a key does. Default key is `&'.
- #whatis
- Show what type of thing a symbol corresponds to. Default
- key is `/'.
- #wield
- Wield a weapon. Default key is `w'.
+ NetHack Guidebook 24
- NetHack 3.6 March 4, 2020
+ #seenv
+ Show seen vectors. Autocompletes. Debug mode only.
+ #seerings
+ Show the ring(s) currently worn. Default key is `='.
+ #seespells
+ List and reorder known spells. Default key is `+'.
+ #seetools
+ Show the tools currently in use. Default key is `('.
- NetHack Guidebook 26
+ #seetrap
+ Show the type of an adjacent trap. Default key is `^'.
+ #seeweapon
+ Show the weapon currently wielded. Default key is `)'.
+ #shell
+ Do a shell escape. Default key is `!'.
- #wipe
- Wipe off your face. Autocompletes. Default key is `M-w'.
+ #sit
+ Sit down. Autocompletes. Default key is `M-s'.
- #wizbury
- Bury objects under and around you. Autocompletes. Debug
- mode only.
+ #stats
+ Show memory usage statistics. Autocompletes. Debug mode only.
- #wizdetect
- Search for hidden things (secret doors or traps or unseen
- monsters) within a modest radius. Autocompletes. Debug
- mode only. Default key is `^E'.
+ #suspend
+ Suspend the game. Default key is `^Z'.
- #wizgenesis
- Create a monster. May be prefixed by a count to create more
- than one. Autocompletes. Debug mode only. Default key is
- `^G'.
+ #swap
+ Swap wielded and secondary weapons. Default key is `x'.
- #wizidentify
- Identify all items in inventory. Autocompletes. Debug mode
- only. Default key is `^I'.
+ #takeoff
+ Take off one piece of armor. Default key is `T'.
- #wizintrinsic
- Set one or more intrinsic attributes. Autocompletes. Debug
- mode only.
+ #takeoffall
+ Remove all armor. Default key is `A'.
- #wizlevelport
- Teleport to another level. Autocompletes. Debug mode only.
- Default key is `^V'.
+ #teleport
+ Teleport around the level. Default key is `^T'.
- #wizmap
- Map the level. Autocompletes. Debug mode only. Default
- key is `^F'.
+ #terrain
+ Show bare map without displaying monsters, objects, or traps.
+ Autocompletes.
- #wizrumorcheck
- Verify rumor boundaries. Autocompletes. Debug mode only.
+ #therecmdmenu
+ Show a menu of possible actions in a location next to you.
- #wizsmell
- Smell monster. Autocompletes. Debug mode only.
+ #throw
+ Throw something. Default key is `t'.
- #wizwhere
- Show locations of special levels. Autocompletes. Debug
- mode only.
+ #timeout
+ Look at the timeout queue. Autocompletes. Debug mode only.
- #wizwish
- Wish for something. Autocompletes. Debug mode only. De-
- fault key is `^W'.
- #wmode
- Show wall modes. Autocompletes. Debug mode only.
+ NetHack 3.6.7 February 3, 2023
- #zap
- Zap a wand. Default key is `z'.
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 25
+ #tip
+ Tip over a container (bag or box) to pour out its contents.
+ Autocompletes. Default key is `M-T'. The `m' prefix makes the
+ command use a menu.
+ #travel
+ Travel to a specific location on the map. Default key is `_'.
+ Using the "request menu" prefix shows a menu of interesting tar-
+ gets in sight without asking to move the cursor. When picking a
+ target with cursor and the autodescribe option is on, the top
+ line will show "(no travel path)" if your character does not know
+ of a path to that location.
- NetHack Guidebook 27
+ #turn
+ Turn undead away. Autocompletes. Default key is `M-t'.
+ #twoweapon
+ Toggle two-weapon combat on or off. Autocompletes. Default key
+ is `X', and also `M-2' if number_pad is off.
+ Note that you must use suitable weapons for this type of combat,
+ or it will be automatically turned off.
- #?
- Help menu: get the list of available extended commands.
+ #untrap
+ Untrap something (trap, door, or chest). Default key is `M-u',
+ and `u' if number_pad is on.
+ In some circumstances it can also be used to rescue trapped mon-
+ sters.
+ #up
+ Go up a staircase. Default key is `<'.
- If your keyboard has a meta key (which, when pressed in com-
- bination with another key, modifies it by setting the "meta"
- [8th, or "high"] bit), you can invoke many extended commands by
- meta-ing the first letter of the command.
+ #vanquished
+ List vanquished monsters. Autocompletes. Debug mode only.
- In NT, OS/2, PC and ST NetHack, the "Alt" key can be used in
- this fashion; on the Amiga, set the altmeta option to get this
- behavior. On other systems, if typing "Alt" plus another key
- transmits a two character sequence consisting of an Escape fol-
- lowed by the other key, you may set the altmeta option to have
- NetHack combine them into meta+key.
+ #version
+ Print compile time options for this version of NetHack. Autocom-
+ pletes. Default key is `M-v'.
- M-? #? (not supported by all platforms)
+ #versionshort
+ Show version string. Default key is `v'.
- M-2 #twoweapon (unless the number_pad option is enabled)
+ #vision
+ Show vision array. Autocompletes. Debug mode only.
- M-a #adjust
+ #wait
+ Rest one move while doing nothing. Default key is `.', and also
+ ` ' if rest_on_space is on.
- M-A #annotate
+ #wear
+ Wear a piece of armor. Default key is `W'.
- M-c #chat
- M-C #conduct
- M-d #dip
- M-e #enhance
+ NetHack 3.6.7 February 3, 2023
- M-f #force
- M-i #invoke
- M-j #jump
- M-l #loot
- M-m #monster
+ NetHack Guidebook 26
- M-n #name
- M-o #offer
- M-O #overview
+ #whatdoes
+ Tell what a key does. Default key is `&'.
- M-p #pray
+ #whatis
+ Show what type of thing a symbol corresponds to. Default key is
+ `/'.
- M-q #quit
+ #wield
+ Wield a weapon. Default key is `w'.
+ #wipe
+ Wipe off your face. Autocompletes. Default key is `M-w'.
+ #wizbury
+ Bury objects under and around you. Autocompletes. Debug mode
+ only.
+ #wizdetect
+ Search for hidden things (secret doors or traps or unseen mon-
+ sters) within a modest radius. Autocompletes. Debug mode only.
+ Default key is `^E'.
- NetHack 3.6 March 4, 2020
+ #wizgenesis
+ Create a monster. May be prefixed by a count to create more than
+ one. Autocompletes. Debug mode only. Default key is `^G'.
+ #wizidentify
+ Identify all items in inventory. Autocompletes. Debug mode
+ only. Default key is `^I'.
+ #wizintrinsic
+ Set one or more intrinsic attributes. Autocompletes. Debug mode
+ only.
+ #wizlevelport
+ Teleport to another level. Autocompletes. Debug mode only.
+ Default key is `^V'.
+ #wizmap
+ Map the level. Autocompletes. Debug mode only. Default key is
+ `^F'.
- NetHack Guidebook 28
+ #wizrumorcheck
+ Verify rumor boundaries. Autocompletes. Debug mode only.
+ #wizsmell
+ Smell monster. Autocompletes. Debug mode only.
+ #wizwhere
+ Show locations of special levels. Autocompletes. Debug mode
+ only.
- M-r #rub
+ #wizwish
+ Wish for something. Autocompletes. Debug mode only. Default
- M-R #ride
- M-s #sit
+ NetHack 3.6.7 February 3, 2023
- M-t #turn
- M-T #tip
- M-u #untrap
- M-v #version
- M-w #wipe
+ NetHack Guidebook 27
- If the number_pad option is on, some additional letter com-
- mands are available:
+ key is `^W'.
- h #help
+ #wmode
+ Show wall modes. Autocompletes. Debug mode only.
- j #jump
+ #zap
+ Zap a wand. Default key is `z'.
- k #kick
+ #?
+ Help menu: get the list of available extended commands.
- l #loot
- N #name
- u #untrap
+ If your keyboard has a meta key (which, when pressed in combina-
+ tion with another key, modifies it by setting the "meta" [8th, or
+ "high"] bit), you can invoke many extended commands by meta-ing the
+ first letter of the command.
- 5. Rooms and corridors
+ In NT, OS/2, PC and ST NetHack, the "Alt" key can be used in this
+ fashion; on the Amiga, set the altmeta option to get this behavior.
+ On other systems, if typing "Alt" plus another key transmits a two
+ character sequence consisting of an Escape followed by the other key,
+ you may set the altmeta option to have NetHack combine them into
+ meta+key.
- Rooms and corridors in the dungeon are either lit or dark.
- Any lit areas within your line of sight will be displayed; dark
- areas are only displayed if they are within one space of you.
- Walls and corridors remain on the map as you explore them.
+ M-? #? (not supported by all platforms)
- Secret corridors are hidden. You can find them with the `s'
- (search) command.
+ M-2 #twoweapon (unless the number_pad option is enabled)
- 5.1. Doorways
+ M-a #adjust
- Doorways connect rooms and corridors. Some doorways have no
- doors; you can walk right through. Others have doors in them,
- which may be open, closed, or locked. To open a closed door, use
- the `o' (open) command; to close it again, use the `c' (close)
- command.
+ M-A #annotate
- You can get through a locked door by using a tool to pick
- the lock with the `a' (apply) command, or by kicking it open with
- the `^D' (kick) command.
+ M-c #chat
+ M-C #conduct
- NetHack 3.6 March 4, 2020
+ M-d #dip
+ M-e #enhance
+ M-f #force
+ M-i #invoke
+ M-j #jump
- NetHack Guidebook 29
+ M-l #loot
+ M-m #monster
+ M-n #name
- Open doors cannot be entered diagonally; you must approach
- them straight on, horizontally or vertically. Doorways without
- doors are not restricted in this fashion.
- Doors can be useful for shutting out monsters. Most mon-
- sters cannot open doors, although a few don't need to (for exam-
- ple, ghosts can walk through doors).
- Secret doors are hidden. You can find them with the `s'
- (search) command. Once found they are in all ways equivalent to
- normal doors.
- 5.2. Traps (`^')
+ NetHack 3.6.7 February 3, 2023
- There are traps throughout the dungeon to snare the unwary
- delver. For example, you may suddenly fall into a pit and be
- stuck for a few turns trying to climb out. Traps don't appear on
- your map until you see one triggered by moving onto it, see some-
- thing fall into it, or you discover it with the `s' (search) com-
- mand. Monsters can fall prey to traps, too, which can be a very
- useful defensive strategy.
- There is a special pre-mapped branch of the dungeon based on
- the classic computer game "Sokoban." The goal is to push the
- boulders into the pits or holes. With careful foresight, it is
- possible to complete all of the levels according to the tradi-
- tional rules of Sokoban. Some allowances are permitted in case
- the player gets stuck; however, they will lower your luck.
- 5.3. Stairs and ladders (`<', `>')
- In general, each level in the dungeon will have a staircase
- going up (`<') to the previous level and another going down (`>')
- to the next level. There are some exceptions though. For in-
- stance, fairly early in the dungeon you will find a level with
- two down staircases, one continuing into the dungeon and the oth-
- er branching into an area known as the Gnomish Mines. Those
- mines eventually hit a dead end, so after exploring them (if you
- choose to do so), you'll need to climb back up to the main dun-
- geon.
- When you traverse a set of stairs, or trigger a trap which
- sends you to another level, the level you're leaving will be de-
- activated and stored in a file on disk. If you're moving to a
- previously visited level, it will be loaded from its file on disk
- and reactivated. If you're moving to a level which has not yet
- been visited, it will be created (from scratch for most random
- levels, from a template for some "special" levels, or loaded from
- the remains of an earlier game for a "bones" level as briefly de-
- scribed below). Monsters are only active on the current level;
- those on other levels are essentially placed into stasis.
+ NetHack Guidebook 28
- Ordinarily when you climb a set of stairs, you will arrive
- on the corresponding staircase at your destination. However,
- NetHack 3.6 March 4, 2020
+ M-o #offer
+ M-O #overview
+ M-p #pray
+ M-q #quit
+ M-r #rub
- NetHack Guidebook 30
+ M-R #ride
+ M-s #sit
+ M-t #turn
- pets (see below) and some other monsters will follow along if
- they're close enough when you travel up or down stairs, and occa-
- sionally one of these creatures will displace you during the
- climb. When that occurs, the pet or other monster will arrive on
- the staircase and you will end up nearby.
+ M-T #tip
- Ladders serve the same purpose as staircases, and the two
- types of inter-level connections are nearly indistinguishable
- during game play.
+ M-u #untrap
- 5.4. Shops and shopping
+ M-v #version
- Occasionally you will run across a room with a shopkeeper
- near the door and many items lying on the floor. You can buy
- items by picking them up and then using the `p' command. You can
- inquire about the price of an item prior to picking it up by us-
- ing the "#chat" command while standing on it. Using an item pri-
- or to paying for it will incur a charge, and the shopkeeper won't
- allow you to leave the shop until you have paid any debt you owe.
+ M-w #wipe
- You can sell items to a shopkeeper by dropping them to the
- floor while inside a shop. You will either be offered an amount
- of gold and asked whether you're willing to sell, or you'll be
- told that the shopkeeper isn't interested (generally, your item
- needs to be compatible with the type of merchandise carried by
- the shop).
- If you drop something in a shop by accident, the shopkeeper
- will usually claim ownership without offering any compensation.
- You'll have to buy it back if you want to reclaim it.
- Shopkeepers sometimes run out of money. When that happens,
- you'll be offered credit instead of gold when you try to sell
- something. Credit can be used to pay for purchases, but it is
- only good in the shop where it was obtained; other shopkeepers
- won't honor it. (If you happen to find a "credit card" in the
- dungeon, don't bother trying to use it in shops; shopkeepers will
- not accept it.)
+ If the number_pad option is on, some additional letter commands
+ are available:
- The `$' command, which reports the amount of gold you are
- carrying (in inventory, not inside bags or boxes), will also show
- current shop debt or credit, if any. The "Iu" command lists un-
- paid items (those which still belong to the shop) if you are car-
- rying any. The "Ix" command shows an inventory-like display of
- any unpaid items which have been used up, along with other shop
- fees, if any.
+ h #help
- 5.4.1. Shop idiosyncrasies
+ j #jump
- Several aspects of shop behavior might be unexpected.
+ k #kick
- * The price of a given item can vary due to a variety of factors.
+ l #loot
+ N #name
+ u #untrap
+ 5. Rooms and corridors
- NetHack 3.6 March 4, 2020
+ Rooms and corridors in the dungeon are either lit or dark. Any
+ lit areas within your line of sight will be displayed; dark areas are
+ only displayed if they are within one space of you. Walls and corri-
+ dors remain on the map as you explore them.
+ Secret corridors are hidden. You can find them with the `s'
+ (search) command.
- NetHack Guidebook 31
+ NetHack 3.6.7 February 3, 2023
- * A shopkeeper treats the spot immediately inside the door as if
- it were outside the shop.
- * While the shopkeeper watches you like a hawk, he will generally
- ignore any other customers.
- * If a shop is "closed for inventory," it will not open of its
- own accord.
- * Shops do not get restocked with new items, regardless of inven-
- tory depletion.
- 6. Monsters
+ NetHack Guidebook 29
- Monsters you cannot see are not displayed on the screen.
- Beware! You may suddenly come upon one in a dark place. Some
- magic items can help you locate them before they locate you
- (which some monsters can do very well).
- The commands `/' and `;' may be used to obtain information
- about those monsters who are displayed on the screen. The com-
- mand "#name" (by default bound to `C'), allows you to assign a
- name to a monster, which may be useful to help distinguish one
- from another when multiple monsters are present. Assigning a
- name which is just a space will remove any prior name.
- The extended command "#chat" can be used to interact with an
- adjacent monster. There is no actual dialog (in other words, you
- don't get to choose what you'll say), but chatting with some mon-
- sters such as a shopkeeper or the Oracle of Delphi can produce
- useful results.
+ 5.1. Doorways
- 6.1. Fighting
+ Doorways connect rooms and corridors. Some doorways have no
+ doors; you can walk right through. Others have doors in them, which
+ may be open, closed, or locked. To open a closed door, use the `o'
+ (open) command; to close it again, use the `c' (close) command.
- If you see a monster and you wish to fight it, just attempt
- to walk into it. Many monsters you find will mind their own
- business unless you attack them. Some of them are very dangerous
- when angered. Remember: discretion is the better part of valor.
+ You can get through a locked door by using a tool to pick the
+ lock with the `a' (apply) command, or by kicking it open with the `^D'
+ (kick) command.
- In most circumstances, if you attempt to attack a peaceful
- monster by moving into its location, you'll be asked to confirm
- your intent. By default an answer of `y' acknowledges that in-
- tent, which can be error prone if you're using `y' to move. You
- can set the paranoid_confirmation option to require a response of
- "yes" instead.
+ Open doors cannot be entered diagonally; you must approach them
+ straight on, horizontally or vertically. Doorways without doors are
+ not restricted in this fashion.
- If you can't see a monster (if it is invisible, or if you
- are blinded), the symbol `I' will be shown when you learn of its
- presence. If you attempt to walk into it, you will try to fight
- it just like a monster that you can see; of course, if the mon-
- ster has moved, you will attack empty air. If you guess that the
- monster has moved and you don't wish to fight, you can use the
- `m' command to move without fighting; likewise, if you don't re-
- member a monster but want to try fighting anyway, you can use the
+ Doors can be useful for shutting out monsters. Most monsters
+ cannot open doors, although a few don't need to (for example, ghosts
+ can walk through doors).
+ Secret doors are hidden. You can find them with the `s' (search)
+ command. Once found they are in all ways equivalent to normal doors.
- NetHack 3.6 March 4, 2020
+ 5.2. Traps (`^')
+ There are traps throughout the dungeon to snare the unwary
+ delver. For example, you may suddenly fall into a pit and be stuck
+ for a few turns trying to climb out. Traps don't appear on your map
+ until you see one triggered by moving onto it, see something fall into
+ it, or you discover it with the `s' (search) command. Monsters can
+ fall prey to traps, too, which can be a very useful defensive strat-
+ egy.
+ There is a special pre-mapped branch of the dungeon based on the
+ classic computer game "Sokoban." The goal is to push the boulders
+ into the pits or holes. With careful foresight, it is possible to
+ complete all of the levels according to the traditional rules of
+ Sokoban. Some allowances are permitted in case the player gets stuck;
+ however, they will lower your luck.
+ 5.3. Stairs and ladders (`<', `>')
+ In general, each level in the dungeon will have a staircase going
+ up (`<') to the previous level and another going down (`>') to the
+ next level. There are some exceptions though. For instance, fairly
+ early in the dungeon you will find a level with two down staircases,
+ one continuing into the dungeon and the other branching into an area
+ known as the Gnomish Mines. Those mines eventually hit a dead end, so
+ after exploring them (if you choose to do so), you'll need to climb
+ back up to the main dungeon.
- NetHack Guidebook 32
+ When you traverse a set of stairs, or trigger a trap which sends
+ you to another level, the level you're leaving will be deactivated and
+ stored in a file on disk. If you're moving to a previously visited
+ level, it will be loaded from its file on disk and reactivated. If
+ NetHack 3.6.7 February 3, 2023
- `F' command.
- 6.2. Your pet
- You start the game with a little dog (`d'), kitten (`f'), or
- pony (`u'), which follows you about the dungeon and fights mon-
- sters with you. Like you, your pet needs food to survive. Dogs
- and cats usually feed themselves on fresh carrion and other
- meats; horses need vegetarian food which is harder to come by.
- If you're worried about your pet or want to train it, you can
- feed it, too, by throwing it food. A properly trained pet can be
- very useful under certain circumstances.
- Your pet also gains experience from killing monsters, and
- can grow over time, gaining hit points and doing more damage.
- Initially, your pet may even be better at killing things than
- you, which makes pets useful for low-level characters.
- Your pet will follow you up and down staircases if it is
- next to you when you move. Otherwise your pet will be stranded
- and may become wild. Similarly, when you trigger certain types
- of traps which alter your location (for instance, a trap door
- which drops you to a lower dungeon level), any adjacent pet will
- accompany you and any non-adjacent pet will be left behind. Your
- pet may trigger such traps itself; you will not be carried along
- with it even if adjacent at the time.
+ NetHack Guidebook 30
- 6.3. Steeds
- Some types of creatures in the dungeon can actually be rid-
- den if you have the right equipment and skill. Convincing a wild
- beast to let you saddle it up is difficult to say the least.
- Many a dungeoneer has had to resort to magic and wizardry in or-
- der to forge the alliance. Once you do have the beast under your
- control however, you can easily climb in and out of the saddle
- with the "#ride" command. Lead the beast around the dungeon when
- riding, in the same manner as you would move yourself. It is the
- beast that you will see displayed on the map.
- Riding skill is managed by the "#enhance" command. See the
- section on Weapon proficiency for more information about that.
+ you're moving to a level which has not yet been visited, it will be
+ created (from scratch for most random levels, from a template for some
+ "special" levels, or loaded from the remains of an earlier game for a
+ "bones" level as briefly described below). Monsters are only active
+ on the current level; those on other levels are essentially placed
+ into stasis.
- Use the `a' (apply) command and pick a saddle in your inven-
- tory to attempt to put that saddle on an adjacent creature. If
- successful, it will be transferred to that creature's inventory.
+ Ordinarily when you climb a set of stairs, you will arrive on the
+ corresponding staircase at your destination. However, pets (see
+ below) and some other monsters will follow along if they're close
+ enough when you travel up or down stairs, and occasionally one of
+ these creatures will displace you during the climb. When that occurs,
+ the pet or other monster will arrive on the staircase and you will end
+ up nearby.
- Use the "#loot" command while adjacent to a saddled creature
- to try to remove the saddle from that creature. If successful,
- it will be transferred to your inventory.
+ Ladders serve the same purpose as staircases, and the two types
+ of inter-level connections are nearly indistinguishable during game
+ play.
- 6.4. Bones levels
+ 5.4. Shops and shopping
- You may encounter the shades and corpses of other adventur-
- ers (or even former incarnations of yourself!) and their personal
+ Occasionally you will run across a room with a shopkeeper near
+ the door and many items lying on the floor. You can buy items by
+ picking them up and then using the `p' command. You can inquire about
+ the price of an item prior to picking it up by using the "#chat" com-
+ mand while standing on it. Using an item prior to paying for it will
+ incur a charge, and the shopkeeper won't allow you to leave the shop
+ until you have paid any debt you owe.
+ You can sell items to a shopkeeper by dropping them to the floor
+ while inside a shop. You will either be offered an amount of gold and
+ asked whether you're willing to sell, or you'll be told that the shop-
+ keeper isn't interested (generally, your item needs to be compatible
+ with the type of merchandise carried by the shop).
- NetHack 3.6 March 4, 2020
+ If you drop something in a shop by accident, the shopkeeper will
+ usually claim ownership without offering any compensation. You'll
+ have to buy it back if you want to reclaim it.
+ Shopkeepers sometimes run out of money. When that happens,
+ you'll be offered credit instead of gold when you try to sell some-
+ thing. Credit can be used to pay for purchases, but it is only good
+ in the shop where it was obtained; other shopkeepers won't honor it.
+ (If you happen to find a "credit card" in the dungeon, don't bother
+ trying to use it in shops; shopkeepers will not accept it.)
+ The `$' command, which reports the amount of gold you are carry-
+ ing (in inventory, not inside bags or boxes), will also show current
+ shop debt or credit, if any. The "Iu" command lists unpaid items
+ (those which still belong to the shop) if you are carrying any. The
+ "Ix" command shows an inventory-like display of any unpaid items which
+ have been used up, along with other shop fees, if any.
- NetHack Guidebook 33
+ NetHack 3.6.7 February 3, 2023
- effects. Ghosts are hard to kill, but easy to avoid, since
- they're slow and do little damage. You can plunder the deceased
- adventurer's possessions; however, they are likely to be cursed.
- Beware of whatever killed the former player; it is probably still
- lurking around, gloating over its last victory.
- 6.5. Persistence of Monsters
- Monsters (a generic reference which also includes humans and
- pets) are only shown while they can be seen or otherwise sensed.
- Moving to a location where you can't see or sense a monster any
- more will result in it disappearing from your map, similarly if
- it is the one who moved rather than you.
- However, if you encounter a monster which you can't see or
- sense -- perhaps it is invisible and has just tapped you on the
- noggin -- a special "remembered, unseen monster" marker will be
- displayed at the location where you think it is. That will per-
- sist until you have proven that there is no monster there, even
- if the unseen monster moves to another location or you move to a
- spot where the marker's location ordinarily wouldn't be seen any
- more.
+ NetHack Guidebook 31
- 7. Objects
- When you find something in the dungeon, it is common to want
- to pick it up. In NetHack, this is accomplished automatically by
- walking over the object (unless you turn off the autopickup op-
- tion (see below), or move with the `m' prefix (see above)), or
- manually by using the `,' command.
- If you're carrying too many items, NetHack will tell you so
- and you won't be able to pick up anything more. Otherwise, it
- will add the object(s) to your pack and tell you what you just
- picked up.
+ 5.4.1. Shop idiosyncrasies
- As you add items to your inventory, you also add the weight
- of that object to your load. The amount that you can carry de-
- pends on your strength and your constitution. The stronger and
- sturdier you are, the less the additional load will affect you.
- There comes a point, though, when the weight of all of that stuff
- you are carrying around with you through the dungeon will encum-
- ber you. Your reactions will get slower and you'll burn calories
- faster, requiring food more frequently to cope with it. Eventu-
- ally, you'll be so overloaded that you'll either have to discard
- some of what you're carrying or collapse under its weight.
+ Several aspects of shop behavior might be unexpected.
- NetHack will tell you how badly you have loaded yourself.
- If you are encumbered, one of the conditions "Burdened",
- "Stressed", "Strained", "Overtaxed" or "Overloaded" will be shown
- on the bottom line status display.
+ * The price of a given item can vary due to a variety of factors.
- When you pick up an object, it is assigned an inventory let-
- ter. Many commands that operate on objects must ask you to find
+ * A shopkeeper treats the spot immediately inside the door as if it
+ were outside the shop.
+ * While the shopkeeper watches you like a hawk, he will generally
+ ignore any other customers.
- NetHack 3.6 March 4, 2020
+ * If a shop is "closed for inventory," it will not open of its own
+ accord.
+ * Shops do not get restocked with new items, regardless of inventory
+ depletion.
+ 6. Monsters
+ Monsters you cannot see are not displayed on the screen. Beware!
+ You may suddenly come upon one in a dark place. Some magic items can
+ help you locate them before they locate you (which some monsters can
+ do very well).
+ The commands `/' and `;' may be used to obtain information about
+ those monsters who are displayed on the screen. The command "#name"
+ (by default bound to `C'), allows you to assign a name to a monster,
+ which may be useful to help distinguish one from another when multiple
+ monsters are present. Assigning a name which is just a space will
+ remove any prior name.
- NetHack Guidebook 34
+ The extended command "#chat" can be used to interact with an
+ adjacent monster. There is no actual dialog (in other words, you
+ don't get to choose what you'll say), but chatting with some monsters
+ such as a shopkeeper or the Oracle of Delphi can produce useful
+ results.
+ 6.1. Fighting
+ If you see a monster and you wish to fight it, just attempt to
+ walk into it. Many monsters you find will mind their own business
+ unless you attack them. Some of them are very dangerous when angered.
+ Remember: discretion is the better part of valor.
- out which object you want to use. When NetHack asks you to
- choose a particular object you are carrying, you are usually pre-
- sented with a list of inventory letters to choose from (see Com-
- mands, above).
+ In most circumstances, if you attempt to attack a peaceful mon-
+ ster by moving into its location, you'll be asked to confirm your
+ intent. By default an answer of `y' acknowledges that intent, which
+ can be error prone if you're using `y' to move. You can set the para-
+ noid_confirmation option to require a response of "yes" instead.
- Some objects, such as weapons, are easily differentiated.
- Others, like scrolls and potions, are given descriptions which
- vary according to type. During a game, any two objects with the
- same description are the same type. However, the descriptions
- will vary from game to game.
+ If you can't see a monster (if it is invisible, or if you are
+ blinded), the symbol `I' will be shown when you learn of its presence.
+ If you attempt to walk into it, you will try to fight it just like a
- When you use one of these objects, if its effect is obvious,
- NetHack will remember what it is for you. If its effect isn't
- extremely obvious, you will be asked what you want to call this
- type of object so you will recognize it later. You can also use
- the "#name" command, for the same purpose at any time, to name
- all objects of a particular type or just an individual object.
- When you use "#name" on an object which has already been named,
- specifying a space as the value will remove the prior name in-
- stead of assigning a new one.
- 7.1. Curses and Blessings
+ NetHack 3.6.7 February 3, 2023
- Any object that you find may be cursed, even if the object
- is otherwise helpful. The most common effect of a curse is being
- stuck with (and to) the item. Cursed weapons weld themselves to
- your hand when wielded, so you cannot unwield them. Any cursed
- item you wear is not removable by ordinary means. In addition,
- cursed arms and armor usually, but not always, bear negative en-
- chantments that make them less effective in combat. Other cursed
- objects may act poorly or detrimentally in other ways.
- Objects can also be blessed. Blessed items usually work
- better or more beneficially than normal uncursed items. For ex-
- ample, a blessed weapon will do more damage against demons.
- Objects which are neither cursed nor blessed are referred to
- as uncursed. They could just as easily have been described as
- unblessed, but the uncursed designation is what you will see
- within the game. A "glass half full versus glass half empty"
- situation; make of that what you will.
- There are magical means of bestowing or removing curses upon
- objects, so even if you are stuck with one, you can still have
- the curse lifted and the item removed. Priests and Priestesses
- have an innate sensitivity to this property in any object, so
- they can more easily avoid cursed objects than other character
- roles.
- An item with unknown status will be reported in your inven-
- tory with no prefix. An item which you know the state of will be
- distinguished in your inventory by the presence of the word
- "cursed", "uncursed" or "blessed" in the description of the item.
- In some cases "uncursed" will be omitted as being redundant when
+ NetHack Guidebook 32
- NetHack 3.6 March 4, 2020
+ monster that you can see; of course, if the monster has moved, you
+ will attack empty air. If you guess that the monster has moved and
+ you don't wish to fight, you can use the `m' command to move without
+ fighting; likewise, if you don't remember a monster but want to try
+ fighting anyway, you can use the `F' command.
+ 6.2. Your pet
+ You start the game with a little dog (`d'), kitten (`f'), or pony
+ (`u'), which follows you about the dungeon and fights monsters with
+ you. Like you, your pet needs food to survive. Dogs and cats usually
+ feed themselves on fresh carrion and other meats; horses need vegetar-
+ ian food which is harder to come by. If you're worried about your pet
+ or want to train it, you can feed it, too, by throwing it food. A
+ properly trained pet can be very useful under certain circumstances.
+ Your pet also gains experience from killing monsters, and can
+ grow over time, gaining hit points and doing more damage. Initially,
+ your pet may even be better at killing things than you, which makes
+ pets useful for low-level characters.
- NetHack Guidebook 35
+ Your pet will follow you up and down staircases if it is next to
+ you when you move. Otherwise your pet will be stranded and may become
+ wild. Similarly, when you trigger certain types of traps which alter
+ your location (for instance, a trap door which drops you to a lower
+ dungeon level), any adjacent pet will accompany you and any non-adja-
+ cent pet will be left behind. Your pet may trigger such traps itself;
+ you will not be carried along with it even if adjacent at the time.
+ 6.3. Steeds
+ Some types of creatures in the dungeon can actually be ridden if
+ you have the right equipment and skill. Convincing a wild beast to
+ let you saddle it up is difficult to say the least. Many a dungeoneer
+ has had to resort to magic and wizardry in order to forge the
+ alliance. Once you do have the beast under your control however, you
+ can easily climb in and out of the saddle with the "#ride" command.
+ Lead the beast around the dungeon when riding, in the same manner as
+ you would move yourself. It is the beast that you will see displayed
+ on the map.
- enough other information is displayed. The implicit_uncursed op-
- tion can be used to control this; toggle it off to have "un-
- cursed" be displayed even when that can be deduced from other at-
- tributes.
+ Riding skill is managed by the "#enhance" command. See the sec-
+ tion on Weapon proficiency for more information about that.
- 7.2. Weapons (`)')
+ Use the `a' (apply) command and pick a saddle in your inventory
+ to attempt to put that saddle on an adjacent creature. If successful,
+ it will be transferred to that creature's inventory.
- Given a chance, most monsters in the Mazes of Menace will
- gratuitously try to kill you. You need weapons for self-defense
- (killing them first). Without a weapon, you do only 1-2 hit
- points of damage (plus bonuses, if any). Monk characters are an
- exception; they normally do more damage with bare (or gloved)
- hands than they do with weapons.
+ Use the "#loot" command while adjacent to a saddled creature to
+ try to remove the saddle from that creature. If successful, it will
+ be transferred to your inventory.
- There are wielded weapons, like maces and swords, and thrown
- weapons, like arrows and spears. To hit monsters with a weapon,
- you must wield it and attack them, or throw it at them. You can
- simply elect to throw a spear. To shoot an arrow, you should
- first wield a bow, then throw the arrow. Crossbows shoot cross-
- bow bolts. Slings hurl rocks and (other) stones (like gems).
- Enchanted weapons have a "plus" (or "to hit enhancement"
- which can be either positive or negative) that adds to your
- chance to hit and the damage you do to a monster. The only way
- to determine a weapon's enchantment is to have it magically iden-
- tified somehow. Most weapons are subject to some type of damage
- like rust. Such "erosion" damage can be repaired.
- The chance that an attack will successfully hit a monster,
- and the amount of damage such a hit will do, depends upon many
- factors. Among them are: type of weapon, quality of weapon (en-
- chantment and/or erosion), experience level, strength, dexterity,
- encumbrance, and proficiency (see below). The monster's armor
- class -- a general defense rating, not necessarily due to wearing
- of armor -- is a factor too; also, some monsters are particularly
- vulnerable to certain types of weapons.
- Many weapons can be wielded in one hand; some require both
- hands. When wielding a two-handed weapon, you can not wear a
- shield, and vice versa. When wielding a one-handed weapon, you
- can have another weapon ready to use by setting things up with
- the `x' command, which exchanges your primary (the one being
- wielded) and alternate weapons. And if you have proficiency in
- the "two weapon combat" skill, you may wield both weapons simul-
- taneously as primary and secondary; use the `X' command to engage
- or disengage that. Only some types of characters (barbarians,
- for instance) have the necessary skill available. Even with that
- skill, using two weapons at once incurs a penalty in the chance
- to hit your target compared to using just one weapon at a time.
- There might be times when you'd rather not wield any weapon
- at all. To accomplish that, wield `-', or else use the `A' com-
- mand which allows you to unwield the current weapon in addition
- to taking off other worn items.
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 33
- NetHack Guidebook 36
+ 6.4. Bones levels
+ You may encounter the shades and corpses of other adventurers (or
+ even former incarnations of yourself!) and their personal effects.
+ Ghosts are hard to kill, but easy to avoid, since they're slow and do
+ little damage. You can plunder the deceased adventurer's possessions;
+ however, they are likely to be cursed. Beware of whatever killed the
+ former player; it is probably still lurking around, gloating over its
+ last victory.
- Those of you in the audience who are AD&D players, be aware
- that each weapon which existed in AD&D does roughly the same dam-
- age to monsters in NetHack. Some of the more obscure weapons
- (such as the aklys, lucern hammer, and bec-de-corbin) are defined
- in an appendix to Unearthed Arcana, an AD&D supplement.
+ 6.5. Persistence of Monsters
- The commands to use weapons are `w' (wield), `t' (throw),
- `f' (fire, an alternate way of throwing), `Q' (quiver), `x' (ex-
- change), `X' (twoweapon), and "#enhance" (see below).
+ Monsters (a generic reference which also includes humans and
+ pets) are only shown while they can be seen or otherwise sensed. Mov-
+ ing to a location where you can't see or sense a monster any more will
+ result in it disappearing from your map, similarly if it is the one
+ who moved rather than you.
- 7.2.1. Throwing and shooting
+ However, if you encounter a monster which you can't see or sense
+ -- perhaps it is invisible and has just tapped you on the noggin -- a
+ special "remembered, unseen monster" marker will be displayed at the
+ location where you think it is. That will persist until you have
+ proven that there is no monster there, even if the unseen monster
+ moves to another location or you move to a spot where the marker's
+ location ordinarily wouldn't be seen any more.
- You can throw just about anything via the `t' command. It
- will prompt for the item to throw; picking `?' will list things
- in your inventory which are considered likely to be thrown, or
- picking `*' will list your entire inventory. After you've chosen
- what to throw, you will be prompted for a direction rather than
- for a specific target. The distance something can be thrown de-
- pends mainly on the type of object and your strength. Arrows can
- be thrown by hand, but can be thrown much farther and will be
- more likely to hit when thrown while you are wielding a bow.
+ 7. Objects
- You can simplify the throwing operation by using the `Q'
- command to select your preferred "missile", then using the `f'
- command to throw it. You'll be prompted for a direction as
- above, but you don't have to specify which item to throw each
- time you use `f'. There is also an option, autoquiver, which has
- NetHack choose another item to automatically fill your quiver (or
- quiver sack, or have at the ready) when the inventory slot used
- for `Q' runs out.
+ When you find something in the dungeon, it is common to want to
+ pick it up. In NetHack, this is accomplished automatically by walking
+ over the object (unless you turn off the autopickup option (see
+ below), or move with the `m' prefix (see above)), or manually by using
+ the `,' command.
- Some characters have the ability to fire a volley of multi-
- ple items in a single turn. Knowing how to load several rounds
- of ammunition at once -- or hold several missiles in your hand --
- and still hit a target is not an easy task. Rangers are among
- those who are adept at this task, as are those with a high level
- of proficiency in the relevant weapon skill (in bow skill if
- you're wielding one to shoot arrows, in crossbow skill if you're
- wielding one to shoot bolts, or in sling skill if you're wielding
- one to shoot stones). The number of items that the character has
- a chance to fire varies from turn to turn. You can explicitly
- limit the number of shots by using a numeric prefix before the
- `t' or `f' command. For example, "2f" (or "n2f" if using num-
- ber_pad mode) would ensure that at most 2 arrows are shot even if
- you could have fired 3. If you specify a larger number than
- would have been shot ("4f" in this example), you'll just end up
- shooting the same number (3, here) as if no limit had been speci-
- fied. Once the volley is in motion, all of the items will travel
- in the same direction; if the first ones kill a monster, the oth-
- ers can still continue beyond that spot.
+ If you're carrying too many items, NetHack will tell you so and
+ you won't be able to pick up anything more. Otherwise, it will add
+ the object(s) to your pack and tell you what you just picked up.
+ As you add items to your inventory, you also add the weight of
+ that object to your load. The amount that you can carry depends on
+ your strength and your constitution. The stronger and sturdier you
+ are, the less the additional load will affect you. There comes a
+ point, though, when the weight of all of that stuff you are carrying
+ around with you through the dungeon will encumber you. Your reactions
+ will get slower and you'll burn calories faster, requiring food more
+ frequently to cope with it. Eventually, you'll be so overloaded that
+ you'll either have to discard some of what you're carrying or collapse
+ under its weight.
+ NetHack will tell you how badly you have loaded yourself. If you
+ are encumbered, one of the conditions "Burdened", "Stressed",
+ "Strained", "Overtaxed" or "Overloaded" will be shown on the bottom
+ line status display.
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 34
- NetHack Guidebook 37
+ When you pick up an object, it is assigned an inventory letter.
+ Many commands that operate on objects must ask you to find out which
+ object you want to use. When NetHack asks you to choose a particular
+ object you are carrying, you are usually presented with a list of
+ inventory letters to choose from (see Commands, above).
- 7.2.2. Weapon proficiency
+ Some objects, such as weapons, are easily differentiated. Oth-
+ ers, like scrolls and potions, are given descriptions which vary
+ according to type. During a game, any two objects with the same
+ description are the same type. However, the descriptions will vary
+ from game to game.
- You will have varying degrees of skill in the weapons avail-
- able. Weapon proficiency, or weapon skills, affect how well you
- can use particular types of weapons, and you'll be able to im-
- prove your skills as you progress through a game, depending on
- your role, your experience level, and use of the weapons.
+ When you use one of these objects, if its effect is obvious,
+ NetHack will remember what it is for you. If its effect isn't
+ extremely obvious, you will be asked what you want to call this type
+ of object so you will recognize it later. You can also use the
+ "#name" command, for the same purpose at any time, to name all objects
+ of a particular type or just an individual object. When you use
+ "#name" on an object which has already been named, specifying a space
+ as the value will remove the prior name instead of assigning a new
+ one.
- For the purposes of proficiency, weapons have been divided
- up into various groups such as daggers, broadswords, and
- polearms. Each role has a limit on what level of proficiency a
- character can achieve for each group. For instance, wizards can
- become highly skilled in daggers or staves but not in swords or
- bows.
+ 7.1. Curses and Blessings
- The "#enhance" extended command is used to review current
- weapons proficiency (also spell proficiency) and to choose which
- skill(s) to improve when you've used one or more skills enough to
- become eligible to do so. The skill rankings are "none" (some-
- times also referred to as "restricted", because you won't be able
- to advance), "unskilled", "basic", "skilled", and "expert". Re-
- stricted skills simply will not appear in the list shown by "#en-
- hance". (Divine intervention might unrestrict a particular
- skill, in which case it will start at unskilled and be limited to
- basic.) Some characters can enhance their barehanded combat or
- martial arts skill beyond expert to "master" or "grand master".
+ Any object that you find may be cursed, even if the object is
+ otherwise helpful. The most common effect of a curse is being stuck
+ with (and to) the item. Cursed weapons weld themselves to your hand
+ when wielded, so you cannot unwield them. Any cursed item you wear is
+ not removable by ordinary means. In addition, cursed arms and armor
+ usually, but not always, bear negative enchantments that make them
+ less effective in combat. Other cursed objects may act poorly or
+ detrimentally in other ways.
- Use of a weapon in which you're restricted or unskilled will
- incur a modest penalty in the chance to hit a monster and also in
- the amount of damage done when you do hit; at basic level, there
- is no penalty or bonus; at skilled level, you receive a modest
- bonus in the chance to hit and amount of damage done; at expert
- level, the bonus is higher. A successful hit has a chance to
- boost your training towards the next skill level (unless you've
- already reached the limit for this skill). Once such training
- reaches the threshold for that next level, you'll be told that
- you feel more confident in your skills. At that point you can
- use "#enhance" to increase one or more skills. Such skills are
- not increased automatically because there is a limit to your to-
- tal overall skills, so you need to actively choose which skills
- to enhance and which to ignore.
+ Objects can also be blessed. Blessed items usually work better
+ or more beneficially than normal uncursed items. For example, a
+ blessed weapon will do more damage against demons.
- 7.2.3. Two-Weapon combat
+ Objects which are neither cursed nor blessed are referred to as
+ uncursed. They could just as easily have been described as unblessed,
+ but the uncursed designation is what you will see within the game. A
+ "glass half full versus glass half empty" situation; make of that what
+ you will.
- Some characters can use two weapons at once. Setting things
- up to do so can seem cumbersome but becomes second nature with
- use. To wield two weapons, you need to use the "#twoweapon" com-
- mand. But first you need to have a weapon in each hand. (Note
- that your two weapons are not fully equal; the one in the hand
- you normally wield with is considered primary and the other one
- is considered secondary. The most noticeable difference is after
- you stop -- or before you begin, for that matter -- wielding two
- weapons at once. The primary is your wielded weapon and the sec-
- ondary is just an item in your inventory that's been designated
+ There are magical means of bestowing or removing curses upon
+ objects, so even if you are stuck with one, you can still have the
+ curse lifted and the item removed. Priests and Priestesses have an
+ innate sensitivity to this property in any object, so they can more
+ easily avoid cursed objects than other character roles.
+ An item with unknown status will be reported in your inventory
+ with no prefix. An item which you know the state of will be distin-
+ guished in your inventory by the presence of the word "cursed",
+ "uncursed" or "blessed" in the description of the item. In some cases
+ "uncursed" will be omitted as being redundant when enough other infor-
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 38
+ NetHack Guidebook 35
- as alternate weapon.)
- If your primary weapon is wielded but your off hand is empty
- or has the wrong weapon, use the sequence `x', `w', `x' to first
- swap your primary into your off hand, wield whatever you want as
- secondary weapon, then swap them both back into the intended
- hands. If your secondary or alternate weapon is correct but your
- primary one is not, simply use `w' to wield the primary. Lastly,
- if neither hand holds the correct weapon, use `w', `x', `w' to
- first wield the intended secondary, swap it to off hand, and then
- wield the primary.
+ mation is displayed. The implicit_uncursed option can be used to con-
+ trol this; toggle it off to have "uncursed" be displayed even when
+ that can be deduced from other attributes.
- The whole process can be simplified via use of the push-
- weapon option. When it is enabled, then using `w' to wield some-
- thing causes the currently wielded weapon to become your alter-
- nate weapon. So the sequence `w', `w' can be used to first wield
- the weapon you intend to be secondary, and then wield the one you
- want as primary which will push the first into secondary posi-
- tion.
+ 7.2. Weapons (`)')
- When in two-weapon combat mode, using the `X' command tog-
- gles back to single-weapon mode. Throwing or dropping either of
- the weapons or having one of them be stolen or destroyed will al-
- so make you revert to single-weapon combat.
+ Given a chance, most monsters in the Mazes of Menace will gratu-
+ itously try to kill you. You need weapons for self-defense (killing
+ them first). Without a weapon, you do only 1-2 hit points of damage
+ (plus bonuses, if any). Monk characters are an exception; they nor-
+ mally do more damage with bare (or gloved) hands than they do with
+ weapons.
- 7.3. Armor (`[')
+ There are wielded weapons, like maces and swords, and thrown
+ weapons, like arrows and spears. To hit monsters with a weapon, you
+ must wield it and attack them, or throw it at them. You can simply
+ elect to throw a spear. To shoot an arrow, you should first wield a
+ bow, then throw the arrow. Crossbows shoot crossbow bolts. Slings
+ hurl rocks and (other) stones (like gems).
- Lots of unfriendly things lurk about; you need armor to pro-
- tect yourself from their blows. Some types of armor offer better
- protection than others. Your armor class is a measure of this
- protection. Armor class (AC) is measured as in AD&D, with 10 be-
- ing the equivalent of no armor, and lower numbers meaning better
- armor. Each suit of armor which exists in AD&D gives the same
- protection in NetHack. Here is an (incomplete) list of the armor
- classes provided by various suits of armor:
- dragon scale mail 1
- plate mail 3
- crystal plate mail 3
- bronze plate mail 4
- splint mail 4
- banded mail 4
- dwarvish mithril-coat 4
- elven mithril-coat 5
- chain mail 5
- orcish chain mail 6
- scale mail 6
- dragon scales 7
- studded leather armor 7
- ring mail 7
- orcish ring mail 8
- leather armor 8
- leather jacket 9
- no armor 10
+ Enchanted weapons have a "plus" (or "to hit enhancement" which
+ can be either positive or negative) that adds to your chance to hit
+ and the damage you do to a monster. The only way to determine a
+ weapon's enchantment is to have it magically identified somehow. Most
+ weapons are subject to some type of damage like rust. Such "erosion"
+ damage can be repaired.
+ The chance that an attack will successfully hit a monster, and
+ the amount of damage such a hit will do, depends upon many factors.
+ Among them are: type of weapon, quality of weapon (enchantment and/or
+ erosion), experience level, strength, dexterity, encumbrance, and pro-
+ ficiency (see below). The monster's armor class -- a general defense
+ rating, not necessarily due to wearing of armor -- is a factor too;
+ also, some monsters are particularly vulnerable to certain types of
+ weapons.
+ Many weapons can be wielded in one hand; some require both hands.
+ When wielding a two-handed weapon, you can not wear a shield, and vice
+ versa. When wielding a one-handed weapon, you can have another weapon
+ ready to use by setting things up with the `x' command, which
+ exchanges your primary (the one being wielded) and alternate weapons.
+ And if you have proficiency in the "two weapon combat" skill, you may
+ wield both weapons simultaneously as primary and secondary; use the
+ `X' command to engage or disengage that. Only some types of charac-
+ ters (barbarians, for instance) have the necessary skill available.
+ Even with that skill, using two weapons at once incurs a penalty in
+ the chance to hit your target compared to using just one weapon at a
+ time.
- NetHack 3.6 March 4, 2020
+ There might be times when you'd rather not wield any weapon at
+ all. To accomplish that, wield `-', or else use the `A' command which
+ allows you to unwield the current weapon in addition to taking off
+ other worn items.
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 39
- You can also wear other pieces of armor (for example hel-
- mets, boots, shields, cloaks) to lower your armor class even fur-
- ther, but you can only wear one item of each category (one suit
- of armor, one cloak, one helmet, one shield, and so on) at a
- time.
+ NetHack Guidebook 36
- If a piece of armor is enchanted, its armor protection will
- be better (or worse) than normal, and its "plus" (or minus) will
- subtract from your armor class. For example, a +1 chain mail
- would give you better protection than normal chain mail, lowering
- your armor class one unit further to 4. When you put on a piece
- of armor, you immediately find out the armor class and any
- "plusses" it provides. Cursed pieces of armor usually have nega-
- tive enchantments (minuses) in addition to being unremovable.
- Many types of armor are subject to some kind of damage like
- rust. Such damage can be repaired. Some types of armor may in-
- hibit spell casting.
- The commands to use armor are `W' (wear) and `T' (take off).
- The `A' command can also be used to take off armor as well as
- other worn items.
+ Those of you in the audience who are AD&D players, be aware that
+ each weapon which existed in AD&D does roughly the same damage to mon-
+ sters in NetHack. Some of the more obscure weapons (such as the
+ aklys, lucern hammer, and bec-de-corbin) are defined in an appendix to
+ Unearthed Arcana, an AD&D supplement.
- 7.4. Food (`%')
+ The commands to use weapons are `w' (wield), `t' (throw), `f'
+ (fire, an alternate way of throwing), `Q' (quiver), `x' (exchange),
+ `X' (twoweapon), and "#enhance" (see below).
- Food is necessary to survive. If you go too long without
- eating you will faint, and eventually die of starvation. Some
- types of food will spoil, and become unhealthy to eat, if not
- protected. Food stored in ice boxes or tins ("cans") will usual-
- ly stay fresh, but ice boxes are heavy, and tins take a while to
- open.
+ 7.2.1. Throwing and shooting
- When you kill monsters, they usually leave corpses which are
- also "food." Many, but not all, of these are edible; some also
- give you special powers when you eat them. A good rule of thumb
- is "you are what you eat."
+ You can throw just about anything via the `t' command. It will
+ prompt for the item to throw; picking `?' will list things in your
+ inventory which are considered likely to be thrown, or picking `*'
+ will list your entire inventory. After you've chosen what to throw,
+ you will be prompted for a direction rather than for a specific tar-
+ get. The distance something can be thrown depends mainly on the type
+ of object and your strength. Arrows can be thrown by hand, but can be
+ thrown much farther and will be more likely to hit when thrown while
+ you are wielding a bow.
- Some character roles and some monsters are vegetarian. Veg-
- etarian monsters will typically never eat animal corpses, while
- vegetarian players can, but with some rather unpleasant side-ef-
- fects.
+ You can simplify the throwing operation by using the `Q' command
+ to select your preferred "missile", then using the `f' command to
+ throw it. You'll be prompted for a direction as above, but you don't
+ have to specify which item to throw each time you use `f'. There is
+ also an option, autoquiver, which has NetHack choose another item to
+ automatically fill your quiver (or quiver sack, or have at the ready)
+ when the inventory slot used for `Q' runs out.
- You can name one food item after something you like to eat
- with the fruit option.
+ Some characters have the ability to fire a volley of multiple
+ items in a single turn. Knowing how to load several rounds of ammuni-
+ tion at once -- or hold several missiles in your hand -- and still hit
+ a target is not an easy task. Rangers are among those who are adept
+ at this task, as are those with a high level of proficiency in the
+ relevant weapon skill (in bow skill if you're wielding one to shoot
+ arrows, in crossbow skill if you're wielding one to shoot bolts, or in
+ sling skill if you're wielding one to shoot stones). The number of
+ items that the character has a chance to fire varies from turn to
+ turn. You can explicitly limit the number of shots by using a numeric
+ prefix before the `t' or `f' command. For example, "2f" (or "n2f" if
+ using number_pad mode) would ensure that at most 2 arrows are shot
+ even if you could have fired 3. If you specify a larger number than
+ would have been shot ("4f" in this example), you'll just end up shoot-
+ ing the same number (3, here) as if no limit had been specified. Once
+ the volley is in motion, all of the items will travel in the same
+ direction; if the first ones kill a monster, the others can still con-
+ tinue beyond that spot.
- The command to eat food is `e'.
+ 7.2.2. Weapon proficiency
- 7.5. Scrolls (`?')
+ You will have varying degrees of skill in the weapons available.
+ Weapon proficiency, or weapon skills, affect how well you can use par-
+ ticular types of weapons, and you'll be able to improve your skills as
- Scrolls are labeled with various titles, probably chosen by
- ancient wizards for their amusement value (for example "READ ME,"
- or "THANX MAUD" backwards). Scrolls disappear after you read
- them (except for blank ones, without magic spells on them).
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 37
- NetHack Guidebook 40
+ you progress through a game, depending on your role, your experience
+ level, and use of the weapons.
+ For the purposes of proficiency, weapons have been divided up
+ into various groups such as daggers, broadswords, and polearms. Each
+ role has a limit on what level of proficiency a character can achieve
+ for each group. For instance, wizards can become highly skilled in
+ daggers or staves but not in swords or bows.
+
+ The "#enhance" extended command is used to review current weapons
+ proficiency (also spell proficiency) and to choose which skill(s) to
+ improve when you've used one or more skills enough to become eligible
+ to do so. The skill rankings are "none" (sometimes also referred to
+ as "restricted", because you won't be able to advance), "unskilled",
+ "basic", "skilled", and "expert". Restricted skills simply will not
+ appear in the list shown by "#enhance". (Divine intervention might
+ unrestrict a particular skill, in which case it will start at
+ unskilled and be limited to basic.) Some characters can enhance their
+ barehanded combat or martial arts skill beyond expert to "master" or
+ "grand master".
- One of the most useful of these is the scroll of identify,
- which can be used to determine what another object is, whether it
- is cursed or blessed, and how many uses it has left. Some ob-
- jects of subtle enchantment are difficult to identify without
- these.
+ Use of a weapon in which you're restricted or unskilled will
+ incur a modest penalty in the chance to hit a monster and also in the
+ amount of damage done when you do hit; at basic level, there is no
+ penalty or bonus; at skilled level, you receive a modest bonus in the
+ chance to hit and amount of damage done; at expert level, the bonus is
+ higher. A successful hit has a chance to boost your training towards
+ the next skill level (unless you've already reached the limit for this
+ skill). Once such training reaches the threshold for that next level,
+ you'll be told that you feel more confident in your skills. At that
+ point you can use "#enhance" to increase one or more skills. Such
+ skills are not increased automatically because there is a limit to
+ your total overall skills, so you need to actively choose which skills
+ to enhance and which to ignore.
+
+ 7.2.3. Two-Weapon combat
- A mail daemon may run up and deliver mail to you as a scroll
- of mail (on versions compiled with this feature). To use this
- feature on versions where NetHack mail delivery is triggered by
- electronic mail appearing in your system mailbox, you must let
- NetHack know where to look for new mail by setting the "MAIL" en-
- vironment variable to the file name of your mailbox. You may al-
- so want to set the "MAILREADER" environment variable to the file
- name of your favorite reader, so NetHack can shell to it when you
- read the scroll. On versions of NetHack where mail is randomly
- generated internal to the game, these environment variables are
- ignored. You can disable the mail daemon by turning off the mail
- option.
+ Some characters can use two weapons at once. Setting things up
+ to do so can seem cumbersome but becomes second nature with use. To
+ wield two weapons, you need to use the "#twoweapon" command. But
+ first you need to have a weapon in each hand. (Note that your two
+ weapons are not fully equal; the one in the hand you normally wield
+ with is considered primary and the other one is considered secondary.
+ The most noticeable difference is after you stop -- or before you
+ begin, for that matter -- wielding two weapons at once. The primary
+ is your wielded weapon and the secondary is just an item in your
+ inventory that's been designated as alternate weapon.)
- The command to read a scroll is `r'.
+ If your primary weapon is wielded but your off hand is empty or
+ has the wrong weapon, use the sequence `x', `w', `x' to first swap
+ your primary into your off hand, wield whatever you want as secondary
+ weapon, then swap them both back into the intended hands. If your
+ secondary or alternate weapon is correct but your primary one is not,
+ simply use `w' to wield the primary. Lastly, if neither hand holds
- 7.6. Potions (`!')
- Potions are distinguished by the color of the liquid inside
- the flask. They disappear after you quaff them.
+ NetHack 3.6.7 February 3, 2023
- Clear potions are potions of water. Sometimes these are
- blessed or cursed, resulting in holy or unholy water. Holy water
- is the bane of the undead, so potions of holy water are good
- things to throw (`t') at them. It is also sometimes very useful
- to dip ("#dip") an object into a potion.
- The command to drink a potion is `q' (quaff).
- 7.7. Wands (`/')
- Wands usually have multiple magical charges. Some types of
- wands require a direction in which to zap them. You can also zap
- them at yourself (just give a `.' or `s' for the direction). Be
- warned, however, for this is often unwise. Other types of wands
- don't require a direction. The number of charges in a wand is
- random and decreases by one whenever you use it.
- When the number of charges left in a wand becomes zero, at-
- tempts to use the wand will usually result in nothing happening.
- Occasionally, however, it may be possible to squeeze the last few
- mana points from an otherwise spent wand, destroying it in the
- process. A wand may be recharged by using suitable magic, but
- doing so runs the risk of causing it to explode. The chance for
- such an explosion starts out very small and increases each time
- the wand is recharged.
+ NetHack Guidebook 38
- In a truly desperate situation, when your back is up against
- the wall, you might decide to go for broke and break your wand.
- NetHack 3.6 March 4, 2020
+ the correct weapon, use `w', `x', `w' to first wield the intended sec-
+ ondary, swap it to off hand, and then wield the primary.
+ The whole process can be simplified via use of the pushweapon
+ option. When it is enabled, then using `w' to wield something causes
+ the currently wielded weapon to become your alternate weapon. So the
+ sequence `w', `w' can be used to first wield the weapon you intend to
+ be secondary, and then wield the one you want as primary which will
+ push the first into secondary position.
+ When in two-weapon combat mode, using the `X' command toggles
+ back to single-weapon mode. Throwing or dropping either of the weap-
+ ons or having one of them be stolen or destroyed will also make you
+ revert to single-weapon combat.
+ 7.3. Armor (`[')
+ Lots of unfriendly things lurk about; you need armor to protect
+ yourself from their blows. Some types of armor offer better protec-
+ tion than others. Your armor class is a measure of this protection.
+ Armor class (AC) is measured as in AD&D, with 10 being the equivalent
+ of no armor, and lower numbers meaning better armor. Each suit of
+ armor which exists in AD&D gives the same protection in NetHack. Here
+ is an (incomplete) list of the armor classes provided by various suits
+ of armor:
+ dragon scale mail 1
+ plate mail 3
+ crystal plate mail 3
+ bronze plate mail 4
+ splint mail 4
+ banded mail 4
+ dwarvish mithril-coat 4
+ elven mithril-coat 5
+ chain mail 5
+ orcish chain mail 6
+ scale mail 6
+ dragon scales 7
+ studded leather armor 7
+ ring mail 7
+ orcish ring mail 8
+ leather armor 8
+ leather jacket 9
+ no armor 10
- NetHack Guidebook 41
+ You can also wear other pieces of armor (for example helmets,
+ boots, shields, cloaks) to lower your armor class even further, but
+ you can only wear one item of each category (one suit of armor, one
+ cloak, one helmet, one shield, and so on) at a time.
+ If a piece of armor is enchanted, its armor protection will be
+ better (or worse) than normal, and its "plus" (or minus) will subtract
+ from your armor class. For example, a +1 chain mail would give you
+ better protection than normal chain mail, lowering your armor class
+ one unit further to 4. When you put on a piece of armor, you immedi-
- This is not for the faint of heart. Doing so will almost cer-
- tainly cause a catastrophic release of magical energies.
+ NetHack 3.6.7 February 3, 2023
- When you have fully identified a particular wand, inventory
- display will include additional information in parentheses: the
- number of times it has been recharged followed by a colon and
- then by its current number of charges. A current charge count of
- -1 is a special case indicating that the wand has been cancelled.
- The command to use a wand is `z' (zap). To break one, use
- the `a' (apply) command.
- 7.8. Rings (`=')
- Rings are very useful items, since they are relatively per-
- manent magic, unlike the usually fleeting effects of potions,
- scrolls, and wands.
- Putting on a ring activates its magic. You can wear only
- two rings, one on each ring finger.
+ NetHack Guidebook 39
- Most rings also cause you to grow hungry more rapidly, the
- rate varying with the type of ring.
- The commands to use rings are `P' (put on) and `R' (remove).
- 7.9. Spellbooks (`+')
+ ately find out the armor class and any "plusses" it provides. Cursed
+ pieces of armor usually have negative enchantments (minuses) in addi-
+ tion to being unremovable.
- Spellbooks are tomes of mighty magic. When studied with the
- `r' (read) command, they transfer to the reader the knowledge of
- a spell (and therefore eventually become unreadable) -- unless
- the attempt backfires. Reading a cursed spellbook or one with
- mystic runes beyond your ken can be harmful to your health!
+ Many types of armor are subject to some kind of damage like rust.
+ Such damage can be repaired. Some types of armor may inhibit spell
+ casting.
- A spell (even when learned) can also backfire when you cast
- it. If you attempt to cast a spell well above your experience
- level, or if you have little skill with the appropriate spell
- type, or cast it at a time when your luck is particularly bad,
- you can end up wasting both the energy and the time required in
- casting.
+ The commands to use armor are `W' (wear) and `T' (take off). The
+ `A' command can also be used to take off armor as well as other worn
+ items.
- Casting a spell calls forth magical energies and focuses
- them with your naked mind. Some of the magical energy released
- comes from within you. Casting temporarily drains your magical
- power, which will slowly be recovered, and causes you to need ad-
- ditional food. Casting of spells also requires practice. With
- practice, your skill in each category of spell casting will im-
- prove. Over time, however, your memory of each spell will dim,
- and you will need to relearn it.
+ 7.4. Food (`%')
- Some spells require a direction in which to cast them, simi-
- lar to wands. To cast one at yourself, just give a `.' or `s'
- for the direction. A few spells require you to pick a target lo-
- cation rather than just specify a particular direction. Other
+ Food is necessary to survive. If you go too long without eating
+ you will faint, and eventually die of starvation. Some types of food
+ will spoil, and become unhealthy to eat, if not protected. Food
+ stored in ice boxes or tins ("cans") will usually stay fresh, but ice
+ boxes are heavy, and tins take a while to open.
+ When you kill monsters, they usually leave corpses which are also
+ "food." Many, but not all, of these are edible; some also give you
+ special powers when you eat them. A good rule of thumb is "you are
+ what you eat."
- NetHack 3.6 March 4, 2020
+ Some character roles and some monsters are vegetarian. Vegetar-
+ ian monsters will typically never eat animal corpses, while vegetarian
+ players can, but with some rather unpleasant side-effects.
+ You can name one food item after something you like to eat with
+ the fruit option.
+ The command to eat food is `e'.
+ 7.5. Scrolls (`?')
+ Scrolls are labeled with various titles, probably chosen by
+ ancient wizards for their amusement value (for example "READ ME," or
+ "THANX MAUD" backwards). Scrolls disappear after you read them
+ (except for blank ones, without magic spells on them).
- NetHack Guidebook 42
+ One of the most useful of these is the scroll of identify, which
+ can be used to determine what another object is, whether it is cursed
+ or blessed, and how many uses it has left. Some objects of subtle
+ enchantment are difficult to identify without these.
+ A mail daemon may run up and deliver mail to you as a scroll of
+ mail (on versions compiled with this feature). To use this feature on
+ versions where NetHack mail delivery is triggered by electronic mail
+ appearing in your system mailbox, you must let NetHack know where to
+ look for new mail by setting the "MAIL" environment variable to the
+ file name of your mailbox. You may also want to set the "MAILREADER"
+ environment variable to the file name of your favorite reader, so
+ NetHack can shell to it when you read the scroll. On versions of
- spells don't require any direction or target.
+ NetHack 3.6.7 February 3, 2023
- Just as weapons are divided into groups in which a character
- can become proficient (to varying degrees), spells are similarly
- grouped. Successfully casting a spell exercises its skill group;
- using the "#enhance" command to advance a sufficiently exercised
- skill will affect all spells within the group. Advanced skill
- may increase the potency of spells, reduce their risk of failure
- during casting attempts, and improve the accuracy of the estimate
- for how much longer they will be retained in your memory. Skill
- slots are shared with weapons skills. (See also the section on
- "Weapon proficiency".)
- Casting a spell also requires flexible movement, and wearing
- various types of armor may interfere with that.
- The command to read a spellbook is the same as for scrolls,
- `r' (read). The `+' command lists each spell you know along with
- its level, skill category, chance of failure when casting, and an
- estimate of how strongly it is remembered. The `Z' (cast) com-
- mand casts a spell.
- 7.10. Tools (`(')
- Tools are miscellaneous objects with various purposes. Some
- tools have a limited number of uses, akin to wand charges. For
- example, lamps burn out after a while. Other tools are contain-
- ers, which objects can be placed into or taken out of.
+ NetHack Guidebook 40
- The command to use a tool is `a' (apply).
- 7.10.1. Containers
- You may encounter bags, boxes, and chests in your travels.
- A tool of this sort can be opened with the "#loot" extended com-
- mand when you are standing on top of it (that is, on the same
- floor spot), or with the `a' (apply) command when you are carry-
- ing it. However, chests are often locked, and are in any case
- unwieldy objects. You must set one down before unlocking it by
- using a key or lock-picking tool with the `a' (apply) command, by
- kicking it with the `^D' command, or by using a weapon to force
- the lock with the "#force" extended command.
+ NetHack where mail is randomly generated internal to the game, these
+ environment variables are ignored. You can disable the mail daemon by
+ turning off the mail option.
- Some chests are trapped, causing nasty things to happen when
- you unlock or open them. You can check for and try to deactivate
- traps with the "#untrap" extended command.
+ The command to read a scroll is `r'.
- 7.11. Amulets (`"')
+ 7.6. Potions (`!')
- Amulets are very similar to rings, and often more powerful.
- Like rings, amulets have various magical properties, some benefi-
- cial, some harmful, which are activated by putting them on.
+ Potions are distinguished by the color of the liquid inside the
+ flask. They disappear after you quaff them.
+ Clear potions are potions of water. Sometimes these are blessed
+ or cursed, resulting in holy or unholy water. Holy water is the bane
+ of the undead, so potions of holy water are good things to throw (`t')
+ at them. It is also sometimes very useful to dip ("#dip") an object
+ into a potion.
+ The command to drink a potion is `q' (quaff).
+ 7.7. Wands (`/')
- NetHack 3.6 March 4, 2020
+ Wands usually have multiple magical charges. Some types of wands
+ require a direction in which to zap them. You can also zap them at
+ yourself (just give a `.' or `s' for the direction). Be warned, how-
+ ever, for this is often unwise. Other types of wands don't require a
+ direction. The number of charges in a wand is random and decreases by
+ one whenever you use it.
+ When the number of charges left in a wand becomes zero, attempts
+ to use the wand will usually result in nothing happening. Occasion-
+ ally, however, it may be possible to squeeze the last few mana points
+ from an otherwise spent wand, destroying it in the process. A wand
+ may be recharged by using suitable magic, but doing so runs the risk
+ of causing it to explode. The chance for such an explosion starts out
+ very small and increases each time the wand is recharged.
+ In a truly desperate situation, when your back is up against the
+ wall, you might decide to go for broke and break your wand. This is
+ not for the faint of heart. Doing so will almost certainly cause a
+ catastrophic release of magical energies.
+ When you have fully identified a particular wand, inventory dis-
+ play will include additional information in parentheses: the number of
+ times it has been recharged followed by a colon and then by its cur-
+ rent number of charges. A current charge count of -1 is a special
+ case indicating that the wand has been cancelled.
+ The command to use a wand is `z' (zap). To break one, use the
+ `a' (apply) command.
- NetHack Guidebook 43
+ 7.8. Rings (`=')
+ Rings are very useful items, since they are relatively permanent
+ magic, unlike the usually fleeting effects of potions, scrolls, and
- Only one amulet may be worn at a time, around your neck.
+ NetHack 3.6.7 February 3, 2023
- The commands to use amulets are the same as for rings, `P'
- (put on) and `R' (remove).
- 7.12. Gems (`*')
- Some gems are valuable, and can be sold for a lot of gold.
- They are also a far more efficient way of carrying your riches.
- Valuable gems increase your score if you bring them with you when
- you exit.
- Other small rocks are also categorized as gems, but they are
- much less valuable. All rocks, however, can be used as projec-
- tile weapons (if you have a sling). In the most desperate of
- cases, you can still throw them by hand.
- 7.13. Large rocks (``')
+ NetHack Guidebook 41
- Statues and boulders are not particularly useful, and are
- generally heavy. It is rumored that some statues are not what
- they seem.
- Very large humanoids (giants and their ilk) have been known
- to use boulders as weapons.
- For some configurations of the program, statues are no
- longer shown as ``' but by the letter representing the monster
- they depict instead.
+ wands.
- 7.14. Gold (`$')
+ Putting on a ring activates its magic. You can wear only two
+ rings, one on each ring finger.
- Gold adds to your score, and you can buy things in shops
- with it. There are a number of monsters in the dungeon that may
- be influenced by the amount of gold you are carrying (shopkeepers
- aside).
+ Most rings also cause you to grow hungry more rapidly, the rate
+ varying with the type of ring.
- 7.15. Persistence of Objects
+ The commands to use rings are `P' (put on) and `R' (remove).
- Normally, if you have seen an object at a particular map lo-
- cation and move to another location where you can't directly see
- that object any more, if will continue to be displayed on your
- map. That remains the case even if it is not actually there any
- more -- perhaps a monster has picked it up or it has rotted away
- -- until you can see or feel that location again. One notable
- exception is that if the object gets covered by the "remembered,
- unseen monster" marker. When that marker is later removed after
- you've verified that no monster is there, you will forget that
- there was any object there regardless of whether the unseen mon-
- ster actually took the object. If the object is still there,
- then once you see or feel that location again you will re-discov-
- er the object and resume remembering it.
+ 7.9. Spellbooks (`+')
+ Spellbooks are tomes of mighty magic. When studied with the `r'
+ (read) command, they transfer to the reader the knowledge of a spell
+ (and therefore eventually become unreadable) -- unless the attempt
+ backfires. Reading a cursed spellbook or one with mystic runes beyond
+ your ken can be harmful to your health!
+ A spell (even when learned) can also backfire when you cast it.
+ If you attempt to cast a spell well above your experience level, or if
+ you have little skill with the appropriate spell type, or cast it at a
+ time when your luck is particularly bad, you can end up wasting both
+ the energy and the time required in casting.
+ Casting a spell calls forth magical energies and focuses them
+ with your naked mind. Some of the magical energy released comes from
+ within you. Casting temporarily drains your magical power, which will
+ slowly be recovered, and causes you to need additional food. Casting
+ of spells also requires practice. With practice, your skill in each
+ category of spell casting will improve. Over time, however, your mem-
+ ory of each spell will dim, and you will need to relearn it.
- NetHack 3.6 March 4, 2020
+ Some spells require a direction in which to cast them, similar to
+ wands. To cast one at yourself, just give a `.' or `s' for the direc-
+ tion. A few spells require you to pick a target location rather than
+ just specify a particular direction. Other spells don't require any
+ direction or target.
+ Just as weapons are divided into groups in which a character can
+ become proficient (to varying degrees), spells are similarly grouped.
+ Successfully casting a spell exercises its skill group; using the
+ "#enhance" command to advance a sufficiently exercised skill will
+ affect all spells within the group. Advanced skill may increase the
+ potency of spells, reduce their risk of failure during casting
+ attempts, and improve the accuracy of the estimate for how much longer
+ they will be retained in your memory. Skill slots are shared with
+ weapons skills. (See also the section on "Weapon proficiency".)
+ Casting a spell also requires flexible movement, and wearing var-
+ ious types of armor may interfere with that.
+ The command to read a spellbook is the same as for scrolls, `r'
+ (read). The `+' command lists each spell you know along with its
+ level, skill category, chance of failure when casting, and an estimate
- NetHack Guidebook 44
+ NetHack 3.6.7 February 3, 2023
- The situation is the same for a pile of objects, except that
- only the top item of the pile is displayed. The hilite_pile op-
- tion can be enabled in order to show an item differently when it
- is the top one of a pile.
- 8. Conduct
- As if winning NetHack were not difficult enough, certain
- players seek to challenge themselves by imposing restrictions on
- the way they play the game. The game automatically tracks some
- of these challenges, which can be checked at any time with the
- #conduct command or at the end of the game. When you perform an
- action which breaks a challenge, it will no longer be listed.
- This gives players extra "bragging rights" for winning the game
- with these challenges. Note that it is perfectly acceptable to
- win the game without resorting to these restrictions and that it
- is unusual for players to adhere to challenges the first time
- they win the game.
+ NetHack Guidebook 42
- Several of the challenges are related to eating behavior.
- The most difficult of these is the foodless challenge. Although
- creatures can survive long periods of time without food, there is
- a physiological need for water; thus there is no restriction on
- drinking beverages, even if they provide some minor food bene-
- fits. Calling upon your god for help with starvation does not
- violate any food challenges either.
- A strict vegan diet is one which avoids any food derived
- from animals. The primary source of nutrition is fruits and veg-
- etables. The corpses and tins of blobs (`b'), jellies (`j'), and
- fungi (`F') are also considered to be vegetable matter. Certain
- human food is prepared without animal products; namely, lembas
- wafers, cram rations, food rations (gunyoki), K-rations, and C-
- rations. Metal or another normally indigestible material eaten
- while polymorphed into a creature that can digest it is also con-
- sidered vegan food. Note however that eating such items still
- counts against foodless conduct.
- Vegetarians do not eat animals; however, they are less se-
- lective about eating animal byproducts than vegans. In addition
- to the vegan items listed above, they may eat any kind of pudding
- (`P') other than the black puddings, eggs and food made from eggs
- (fortune cookies and pancakes), food made with milk (cream pies
- and candy bars), and lumps of royal jelly. Monks are expected to
- observe a vegetarian diet.
+ of how strongly it is remembered. The `Z' (cast) command casts a
+ spell.
- Eating any kind of meat violates the vegetarian, vegan, and
- foodless conducts. This includes tripe rations, the corpses or
- tins of any monsters not mentioned above, and the various other
- chunks of meat found in the dungeon. Swallowing and digesting a
- monster while polymorphed is treated as if you ate the creature's
- corpse. Eating leather, dragon hide, or bone items while poly-
- morphed into a creature that can digest it, or eating monster
- brains while polymorphed into a mind flayer, is considered eating
+ 7.10. Tools (`(')
+ Tools are miscellaneous objects with various purposes. Some
+ tools have a limited number of uses, akin to wand charges. For exam-
+ ple, lamps burn out after a while. Other tools are containers, which
+ objects can be placed into or taken out of.
- NetHack 3.6 March 4, 2020
+ The command to use a tool is `a' (apply).
+ 7.10.1. Containers
+ You may encounter bags, boxes, and chests in your travels. A
+ tool of this sort can be opened with the "#loot" extended command when
+ you are standing on top of it (that is, on the same floor spot), or
+ with the `a' (apply) command when you are carrying it. However,
+ chests are often locked, and are in any case unwieldy objects. You
+ must set one down before unlocking it by using a key or lock-picking
+ tool with the `a' (apply) command, by kicking it with the `^D' com-
+ mand, or by using a weapon to force the lock with the "#force"
+ extended command.
+ Some chests are trapped, causing nasty things to happen when you
+ unlock or open them. You can check for and try to deactivate traps
+ with the "#untrap" extended command.
+ 7.11. Amulets (`"')
- NetHack Guidebook 45
+ Amulets are very similar to rings, and often more powerful. Like
+ rings, amulets have various magical properties, some beneficial, some
+ harmful, which are activated by putting them on.
+ Only one amulet may be worn at a time, around your neck.
+ The commands to use amulets are the same as for rings, `P' (put
+ on) and `R' (remove).
- an animal, although wax is only an animal byproduct.
+ 7.12. Gems (`*')
- Regardless of conduct, there will be some items which are
- indigestible, and others which are hazardous to eat. Using a
- swallow-and-digest attack against a monster is equivalent to eat-
- ing the monster's corpse. Please note that the term "vegan" is
- used here only in the context of diet. You are still free to
- choose not to use or wear items derived from animals (e.g.
- leather, dragon hide, bone, horns, coral), but the game will not
- keep track of this for you. Also note that "milky" potions may
- be a translucent white, but they do not contain milk, so they are
- compatible with a vegan diet. Slime molds or player-defined
- "fruits", although they could be anything from "cherries" to
- "pork chops", are also assumed to be vegan.
+ Some gems are valuable, and can be sold for a lot of gold. They
+ are also a far more efficient way of carrying your riches. Valuable
+ gems increase your score if you bring them with you when you exit.
- An atheist is one who rejects religion. This means that you
- cannot #pray, #offer sacrifices to any god, #turn undead, or
- #chat with a priest. Particularly selective readers may argue
- that playing Monk or Priest characters should violate this con-
- duct; that is a choice left to the player. Offering the Amulet
- of Yendor to your god is necessary to win the game and is not
- counted against this conduct. You are also not penalized for be-
- ing spoken to by an angry god, priest(ess), or other religious
- figure; a true atheist would hear the words but attach no special
- meaning to them.
+ Other small rocks are also categorized as gems, but they are much
+ less valuable. All rocks, however, can be used as projectile weapons
+ (if you have a sling). In the most desperate of cases, you can still
+ throw them by hand.
- Most players fight with a wielded weapon (or tool intended
- to be wielded as a weapon). Another challenge is to win the game
- without using such a wielded weapon. You are still permitted to
- throw, fire, and kick weapons; use a wand, spell, or other type
- of item; or fight with your hands and feet.
+ 7.13. Large rocks (``')
- In NetHack, a pacifist refuses to cause the death of any
- other monster (i.e. if you would get experience for the death).
- This is a particularly difficult challenge, although it is still
- possible to gain experience by other means.
+ Statues and boulders are not particularly useful, and are gener-
+ ally heavy. It is rumored that some statues are not what they seem.
- An illiterate character cannot read or write. This includes
- reading a scroll, spellbook, fortune cookie message, or t-shirt;
- writing a scroll; or making an engraving of anything other than a
- single "X" (the traditional signature of an illiterate person).
- Reading an engraving, or any item that is absolutely necessary to
- win the game, is not counted against this conduct. The identity
- of scrolls and spellbooks (and knowledge of spells) in your
- starting inventory is assumed to be learned from your teachers
- prior to the start of the game and isn't counted.
- There are several other challenges tracked by the game. It
- is possible to eliminate one or more species of monsters by geno-
- cide; playing without this feature is considered a challenge.
- When the game offers you an opportunity to genocide monsters, you
- may respond with the monster type "none" if you want to decline.
- You can change the form of an item into another item of the same
- type ("polypiling") or the form of your own body into another
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 43
- NetHack Guidebook 46
+ Very large humanoids (giants and their ilk) have been known to
+ use boulders as weapons.
+ For some configurations of the program, statues are no longer
+ shown as ``' but by the letter representing the monster they depict
+ instead.
- creature ("polyself") by wand, spell, or potion of polymorph;
- avoiding these effects are each considered challenges. Polymor-
- phing monsters, including pets, does not break either of these
- challenges. Finally, you may sometimes receive wishes; a game
- without an attempt to wish for any items is a challenge, as is a
- game without wishing for an artifact (even if the artifact imme-
- diately disappears). When the game offers you an opportunity to
- make a wish for an item, you may choose "nothing" if you want to
- decline.
+ 7.14. Gold (`$')
- 9. Options
+ Gold adds to your score, and you can buy things in shops with it.
+ There are a number of monsters in the dungeon that may be influenced
+ by the amount of gold you are carrying (shopkeepers aside).
- Due to variations in personal tastes and conceptions of how
- NetHack should do things, there are options you can set to change
- how NetHack behaves.
+ 7.15. Persistence of Objects
- 9.1. Setting the options
+ Normally, if you have seen an object at a particular map location
+ and move to another location where you can't directly see that object
+ any more, it will continue to be displayed on your map. That remains
+ the case even if it is not actually there any more -- perhaps a mon-
+ ster has picked it up or it has rotted away -- until you can see or
+ feel that location again. One notable exception is that if the object
+ gets covered by the "remembered, unseen monster" marker. When that
+ marker is later removed after you've verified that no monster is
+ there, you will forget that there was any object there regardless of
+ whether the unseen monster actually took the object. If the object is
+ still there, then once you see or feel that location again you will
+ re-discover the object and resume remembering it.
- Options may be set in a number of ways. Within the game,
- the `O' command allows you to view all options and change most of
- them. You can also set options automatically by placing them in
- a configuration file, or in the NETHACKOPTIONS environment vari-
- able. Some versions of NetHack also have front-end programs that
- allow you to set options before starting the game or a global
- configuration for system administrators.
+ The situation is the same for a pile of objects, except that only
+ the top item of the pile is displayed. The hilite_pile option can be
+ enabled in order to show an item differently when it is the top one of
+ a pile.
- 9.2. Using a configuration file
+ 8. Conduct
- The default name of the configuration file varies on differ-
- ent operating systems.
+ As if winning NetHack were not difficult enough, certain players
+ seek to challenge themselves by imposing restrictions on the way they
+ play the game. The game automatically tracks some of these chal-
+ lenges, which can be checked at any time with the #conduct command or
+ at the end of the game. When you perform an action which breaks a
+ challenge, it will no longer be listed. This gives players extra
+ "bragging rights" for winning the game with these challenges. Note
+ that it is perfectly acceptable to win the game without resorting to
+ these restrictions and that it is unusual for players to adhere to
+ challenges the first time they win the game.
- On UNIX, Linux, and Mac OS X it is ".nethackrc" in the us-
- er's home directory. The file may not exist, but it is a normal
- ASCII text file and can be created with any text editor.
+ Several of the challenges are related to eating behavior. The
+ most difficult of these is the foodless challenge. Although creatures
+ can survive long periods of time without food, there is a physiologi-
+ cal need for water; thus there is no restriction on drinking bever-
+ ages, even if they provide some minor food benefits. Calling upon
+ your god for help with starvation does not violate any food challenges
+ either.
- On Windows, it is ".nethackrc" in the folder "\%USERPRO-
- FILE%\NetHack\3.6". The file may not exist, but it is a normal
- ASCII text file can can be created with any text editor. After
- running NetHack for the first time, you should find a default
- template for the configuration file named ".nethackrc.template"
- in "\%USERPROFILE%\NetHack\3.6". If you had not created the con-
- figuration file, NetHack will create the configuration file for
- you using the default template file.
- On MS-DOS, it is "defaults.nh" in the same folder as
- nethack.exe.
- Any line in the configuration file starting with `#' is
- treated as a comment. Empty lines are ignored.
+ NetHack 3.6.7 February 3, 2023
- Any line beginning with `[' and ending in `]' is considered
- a section marker. The text between the square brackets is the
- section name. Lines after a section marker belong to that sec-
- tion, and are ignored unless a CHOOSE statement was used to
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 44
- NetHack Guidebook 47
+ A strict vegan diet is one which avoids any food derived from
+ animals. The primary source of nutrition is fruits and vegetables.
+ The corpses and tins of blobs (`b'), jellies (`j'), and fungi (`F')
+ are also considered to be vegetable matter. Certain human food is
+ prepared without animal products; namely, lembas wafers, cram rations,
+ food rations (gunyoki), K-rations, and C-rations. Metal or another
+ normally indigestible material eaten while polymorphed into a creature
+ that can digest it is also considered vegan food. Note however that
+ eating such items still counts against foodless conduct.
+ Vegetarians do not eat animals; however, they are less selective
+ about eating animal byproducts than vegans. In addition to the vegan
+ items listed above, they may eat any kind of pudding (`P') other than
+ the black puddings, eggs and food made from eggs (fortune cookies and
+ pancakes), food made with milk (cream pies and candy bars), and lumps
+ of royal jelly. Monks are expected to observe a vegetarian diet.
+ Eating any kind of meat violates the vegetarian, vegan, and food-
+ less conducts. This includes tripe rations, the corpses or tins of
+ any monsters not mentioned above, and the various other chunks of meat
+ found in the dungeon. Swallowing and digesting a monster while poly-
+ morphed is treated as if you ate the creature's corpse. Eating
+ leather, dragon hide, or bone items while polymorphed into a creature
+ that can digest it, or eating monster brains while polymorphed into a
+ mind flayer, is considered eating an animal, although wax is only an
+ animal byproduct.
- select that section. Section names are case insensitive.
+ Regardless of conduct, there will be some items which are indi-
+ gestible, and others which are hazardous to eat. Using a swallow-and-
+ digest attack against a monster is equivalent to eating the monster's
+ corpse. Please note that the term "vegan" is used here only in the
+ context of diet. You are still free to choose not to use or wear
+ items derived from animals (e.g. leather, dragon hide, bone, horns,
+ coral), but the game will not keep track of this for you. Also note
+ that "milky" potions may be a translucent white, but they do not con-
+ tain milk, so they are compatible with a vegan diet. Slime molds or
+ player-defined "fruits", although they could be anything from "cher-
+ ries" to "pork chops", are also assumed to be vegan.
- You can use different configuration statements in the file,
- some of which can be used multiple times. In general, the state-
- ments are written in capital letters, followed by an equals sign,
- followed by settings particular to that statement.
+ An atheist is one who rejects religion. This means that you can-
+ not #pray, #offer sacrifices to any god, #turn undead, or #chat with a
+ priest. Particularly selective readers may argue that playing Monk or
+ Priest characters should violate this conduct; that is a choice left
+ to the player. Offering the Amulet of Yendor to your god is necessary
+ to win the game and is not counted against this conduct. You are also
+ not penalized for being spoken to by an angry god, priest(ess), or
+ other religious figure; a true atheist would hear the words but attach
+ no special meaning to them.
- Here is a list of allowed statements:
+ Most players fight with a wielded weapon (or tool intended to be
+ wielded as a weapon). Another challenge is to win the game without
+ using such a wielded weapon. You are still permitted to throw, fire,
+ and kick weapons; use a wand, spell, or other type of item; or fight
+ with your hands and feet.
- OPTIONS
- There are two types of options, boolean and compound options.
- Boolean options toggle a setting on or off, while compound op-
- tions take more diverse values. Prefix a boolean option with
- "no" or `!' to turn it off. For compound options, the option
- name and value are separated by a colon. Some options are per-
- sistent, and apply only to new games. You can specify multiple
- OPTIONS statements, and multiple options separated by commas in
- a single OPTIONS statement. (Comma separated options are pro-
- cessed from right to left.)
- Example:
+ NetHack 3.6.7 February 3, 2023
- OPTIONS=dogname:Fido
- OPTIONS=!legacy,autopickup,pickup_types:$"=/!?+
- HACKDIR
- Default location of files NetHack needs. On Windows HACKDIR
- defaults to the location of the NetHack.exe or NetHackw.exe
- file so setting HACKDIR to override that is not usually neces-
- sary or recommended.
- LEVELDIR
- The location that in-progress level files are stored. Defaults
- to HACKDIR, must be writable.
- SAVEDIR
- The location where saved games are kept. Defaults to HACKDIR,
- must be writable.
- BONESDIR
- The location that bones files are kept. Defaults to HACKDIR,
- must be writable.
+ NetHack Guidebook 45
- LOCKDIR
- The location that file synchronization locks are stored.
- Defaults to HACKDIR, must be writable.
- TROUBLEDIR
- The location that a record of game aborts and self-diagnosed
- game problems is kept. Defaults to HACKDIR, must be writable.
- AUTOCOMPLETE
- Enable or disable an extended command autocompletion. Autocom-
- pletion has no effect for the X11 windowport. You can specify
+ In NetHack, a pacifist refuses to cause the death of any other
+ monster (i.e. if you would get experience for the death). This is a
+ particularly difficult challenge, although it is still possible to
+ gain experience by other means.
+ An illiterate character cannot read or write. This includes
+ reading a scroll, spellbook, fortune cookie message, or t-shirt; writ-
+ ing a scroll; or making an engraving of anything other than a single
+ "X" (the traditional signature of an illiterate person). Reading an
+ engraving, or any item that is absolutely necessary to win the game,
+ is not counted against this conduct. The identity of scrolls and
+ spellbooks (and knowledge of spells) in your starting inventory is
+ assumed to be learned from your teachers prior to the start of the
+ game and isn't counted.
- NetHack 3.6 March 4, 2020
+ There are several other challenges tracked by the game. It is
+ possible to eliminate one or more species of monsters by genocide;
+ playing without this feature is considered a challenge. When the game
+ offers you an opportunity to genocide monsters, you may respond with
+ the monster type "none" if you want to decline. You can change the
+ form of an item into another item of the same type ("polypiling") or
+ the form of your own body into another creature ("polyself") by wand,
+ spell, or potion of polymorph; avoiding these effects are each consid-
+ ered challenges. Polymorphing monsters, including pets, does not
+ break either of these challenges. Finally, you may sometimes receive
+ wishes; a game without an attempt to wish for any items is a chal-
+ lenge, as is a game without wishing for an artifact (even if the arti-
+ fact immediately disappears). When the game offers you an opportunity
+ to make a wish for an item, you may choose "nothing" if you want to
+ decline.
+ 9. Options
+ Due to variations in personal tastes and conceptions of how
+ NetHack should do things, there are options you can set to change how
+ NetHack behaves.
+ 9.1. Setting the options
+ Options may be set in a number of ways. Within the game, the `O'
+ command allows you to view all options and change most of them. You
+ can also set options automatically by placing them in a configuration
+ file, or in the NETHACKOPTIONS environment variable. Some versions of
+ NetHack also have front-end programs that allow you to set options
+ before starting the game or a global configuration for system adminis-
+ trators.
- NetHack Guidebook 48
+ 9.2. Using a configuration file
+ The default name of the configuration file varies on different
+ operating systems.
+ On UNIX, Linux, and Mac OS X it is ".nethackrc" in the user's
+ home directory. The file may not exist, but it is a normal ASCII text
- multiple autocompletions. To enable autocompletion, list the
- extended command. Prefix the command with "!" to disable the
- autocompletion for that command.
- Example:
+ NetHack 3.6.7 February 3, 2023
- AUTOCOMPLETE=zap,!annotate
- AUTOPICKUP_EXCEPTION
- Set exceptions to the pickup_types option. See the "Configur-
- ing Autopickup Exceptions" section.
- BINDINGS
- Change the key bindings of some special keys, menu accelera-
- tors, or extended commands. You can specify multiple bindings.
- Format is key followed by the command, separated by a colon.
- See the "Changing Key Bindings" section for more information.
- Example:
- BIND=^X:getpos.autodescribe
+ NetHack Guidebook 46
- CHOOSE
- Chooses at random one of the comma-separated parameters as an
- active section name. Lines in other sections are ignored.
- Example:
- OPTIONS=color
- CHOOSE=char A,char B
- [char A]
- OPTIONS=role:arc,race:dwa,align:law,gender:fem
- [char B]
- OPTIONS=role:wiz,race:elf,align:cha,gender:mal
+ file and can be created with any text editor.
- MENUCOLOR
- Highlight menu lines with different colors. See the "Configur-
- ing Menu Colors" section.
+ On Windows, it is ".nethackrc" in the folder "\%USERPRO-
+ FILE%\NetHack\(rq. The file may not exist, but it is a normal ASCII
+ text file can can be created with any text editor. After running
+ NetHack for the first time, you should find a default template for the
+ configuration file named ".nethackrc.template" in "\%USERPRO-
+ FILE%\NetHack\(rq. If you had not created the configuration file,
+ NetHack will create the configuration file for you using the default
+ template file.
- MSGTYPE
- Change the way messages are shown in the top status line. See
- the "Configuring Message Types" section.
+ On MS-DOS, it is "defaults.nh" in the same folder as nethack.exe.
- ROGUESYMBOLS
- Custom symbols for for the rogue level's symbol set. See SYM-
- BOLS below.
+ Any line in the configuration file starting with `#' is treated
+ as a comment. Empty lines are ignored.
- SOUND
- Define a sound mapping. See the "Configuring User Sounds" sec-
- tion.
+ Any line beginning with `[' and ending in `]' is considered a
+ section marker. The text between the square brackets is the section
+ name. Lines after a section marker belong to that section, and are
+ ignored unless a CHOOSE statement was used to select that section.
+ Section names are case insensitive.
- SOUNDDIR
- Define the directory that contains the sound files. See the
- "Configuring User Sounds" section.
+ You can use different configuration statements in the file, some
+ of which can be used multiple times. In general, the statements are
+ written in capital letters, followed by an equals sign, followed by
+ settings particular to that statement.
+ Here is a list of allowed statements:
- NetHack 3.6 March 4, 2020
+ OPTIONS
+ There are two types of options, boolean and compound options. Bool-
+ ean options toggle a setting on or off, while compound options take
+ more diverse values. Prefix a boolean option with "no" or `!' to
+ turn it off. For compound options, the option name and value are
+ separated by a colon. Some options are persistent, and apply only
+ to new games. You can specify multiple OPTIONS statements, and mul-
+ tiple options separated by commas in a single OPTIONS statement.
+ (Comma separated options are processed from right to left.)
+ Example:
+ OPTIONS=dogname:Fido
+ OPTIONS=!legacy,autopickup,pickup_types:$"=/!?+
+ HACKDIR
+ Default location of files NetHack needs. On Windows HACKDIR defaults
+ to the location of the NetHack.exe or NetHackw.exe file so setting
+ HACKDIR to override that is not usually necessary or recommended.
+ LEVELDIR
+ The location that in-progress level files are stored. Defaults to
+ HACKDIR, must be writable.
- NetHack Guidebook 49
- SYMBOLS
- Override one or more symbols in the symbol set used for all
- dungeon levels except for the special rogue level. See the
- "Modifying NetHack Symbols" section.
+ NetHack 3.6.7 February 3, 2023
- Example:
- # replace small punctuation (tick marks) with digits
- SYMBOLS=S_boulder:0,S_golem:7
- WIZKIT
- Debug mode only: extra items to add to initial inventory.
- Value is the name of a text file containing a list of item
- names, one per line, up to a maximum of 128 lines. Each line
- is processed by the function that handles wishing.
- Example:
- WIZKIT=~/wizkit.txt
+ NetHack Guidebook 47
- Here is an example of configuration file contents:
+ SAVEDIR
+ The location where saved games are kept. Defaults to HACKDIR, must
+ be writable.
- # Set your character's role, race, gender, and alignment.
- OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful
- #
- # Turn on autopickup, set automatically picked up object types
- OPTIONS=autopickup,pickup_types:$"=/!?+
- #
- # Map customization
- OPTIONS=color # Display things in color if possible
- OPTIONS=lit_corridor # Show lit corridors differently
- OPTIONS=hilite_pet,hilite_pile
- # Replace small punctuation (tick marks) with digits
- SYMBOLS=S_boulder:0,S_golem:7
- #
- # No startup splash screen. Windows GUI only.
- OPTIONS=!splash_screen
+ BONESDIR
+ The location that bones files are kept. Defaults to HACKDIR, must be
+ writable.
+ LOCKDIR
+ The location that file synchronization locks are stored. Defaults to
+ HACKDIR, must be writable.
+ TROUBLEDIR
+ The location that a record of game aborts and self-diagnosed game
+ problems is kept. Defaults to HACKDIR, must be writable.
- 9.3. Using the NETHACKOPTIONS environment variable
+ AUTOCOMPLETE
+ Enable or disable an extended command autocompletion. Autocomple-
+ tion has no effect for the X11 windowport. You can specify multiple
+ autocompletions. To enable autocompletion, list the extended com-
+ mand. Prefix the command with "!" to disable the autocompletion for
+ that command.
- The NETHACKOPTIONS variable is a comma-separated list of
- initial values for the various options. Some can only be turned
- on or off. You turn one of these on by adding the name of the
- option to the list, and turn it off by typing a `!' or "no" be-
- fore the name. Others take a character string as a value. You
- can set string options by typing the option name, a colon or
- equals sign, and then the value of the string. The value is ter-
- minated by the next comma or the end of string.
+ Example:
+ AUTOCOMPLETE=zap,!annotate
+ AUTOPICKUP_EXCEPTION
+ Set exceptions to the pickup_types option. See the "Configuring
+ Autopickup Exceptions" section.
+ BINDINGS
+ Change the key bindings of some special keys, menu accelerators, or
+ extended commands. You can specify multiple bindings. Format is
+ key followed by the command, separated by a colon. See the "Chang-
+ ing Key Bindings" section for more information.
- NetHack 3.6 March 4, 2020
+ Example:
+ BIND=^X:getpos.autodescribe
+ CHOOSE
+ Chooses at random one of the comma-separated parameters as an active
+ section name. Lines in other sections are ignored.
+ Example:
+ OPTIONS=color
+ CHOOSE=char A,char B
+ [char A]
+ OPTIONS=role:arc,race:dwa,align:law,gender:fem
+ [char B]
+ OPTIONS=role:wiz,race:elf,align:cha,gender:mal
- NetHack Guidebook 50
+ NetHack 3.6.7 February 3, 2023
- For example, to set up an environment variable so that color
- is on, legacy is off, character name is set to "Blue Meanie", and
- named fruit is set to "lime", you would enter the command
- % setenv NETHACKOPTIONS "color,\!leg,name:Blue Meanie,fruit:lime"
- in csh (note the need to escape the `!' since it's special to
- that shell), or the pair of commands
- $ NETHACKOPTIONS="color,!leg,name:Blue Meanie,fruit:lime"
- $ export NETHACKOPTIONS
- in sh, ksh, or bash.
+ NetHack Guidebook 48
- The NETHACKOPTIONS value is effectively the same as a single
- OPTIONS statement in a configuration file. The "OPTIONS=" prefix
- is implied and comma separated options are processed from right
- to left. Other types of configuration statements such as BIND or
- MSGTYPE are not allowed.
- Instead of a comma-separated list of options, NETHACKOPTIONS
- can be set to the full name of a configuration file you want to
- use. If that full name doesn't start with a slash, precede it
- with `@' (at-sign) to let NetHack know that the rest is intended
- as a file name. If it does start with `/', the at-sign is op-
- tional.
- 9.4. Customization options
+ MENUCOLOR
+ Highlight menu lines with different colors. See the "Configuring
+ Menu Colors" section.
- Here are explanations of what the various options do. Char-
- acter strings that are too long may be truncated. Some of the
- options listed may be inactive in your dungeon.
+ MSGTYPE
+ Change the way messages are shown in the top status line. See the
+ "Configuring Message Types" section.
- Some options are persistent, and are saved and reloaded
- along with the game. Changing a persistent option in the config-
- uration file applies only to new games.
+ ROGUESYMBOLS
+ Custom symbols for for the rogue level's symbol set. See SYMBOLS
+ below.
- acoustics
- Enable messages about what your character hears (default on).
- Note that this has nothing to do with your computer's audio ca-
- pabilities. Persistent.
+ SOUND
+ Define a sound mapping. See the "Configuring User Sounds" section.
- align
- Your starting alignment (align:lawful, align:neutral, or
- align:chaotic). You may specify just the first letter. The
- default is to randomly pick an appropriate alignment. If you
- prefix the value with `!' or "no", you will exclude that align-
- ment from being picked randomly. Cannot be set with the `O'
- command. Persistent.
+ SOUNDDIR
+ Define the directory that contains the sound files. See the "Con-
+ figuring User Sounds" section.
- autodescribe
- Automatically describe the terrain under cursor when asked to
- get a location on the map (default true). The whatis_coord op-
- tion controls whether the description includes map coordinates.
+ SYMBOLS
+ Override one or more symbols in the symbol set used for all dungeon
+ levels except for the special rogue level. See the "Modifying
+ NetHack Symbols" section.
+ Example:
- NetHack 3.6 March 4, 2020
+ # replace small punctuation (tick marks) with digits
+ SYMBOLS=S_boulder:0,S_golem:7
+ WIZKIT
+ Debug mode only: extra items to add to initial inventory. Value is
+ the name of a text file containing a list of item names, one per
+ line, up to a maximum of 128 lines. Each line is processed by the
+ function that handles wishing.
+ Example:
+ WIZKIT=~/wizkit.txt
- NetHack Guidebook 51
+ Here is an example of configuration file contents:
- autodig
- Automatically dig if you are wielding a digging tool and moving
- into a place that can be dug (default false). Persistent.
- autoopen
- Walking into a door attempts to open it (default true). Persis-
- tent.
- autopickup
- Automatically pick up things onto which you move (default on).
- Persistent. See pickup_types to refine the behavior.
- autoquiver
- This option controls what happens when you attempt the `f'
- (fire) command when nothing is quivered or readied (default
- false). When true, the computer will fill your quiver or
- quiver sack or make ready some suitable weapon. Note that it
- will not take into account the blessed/cursed status, enchant-
- ment, damage, or quality of the weapon; you are free to manual-
- ly fill your quiver or quiver sack or make ready with the `Q'
- command instead. If no weapon is found or the option is false,
- the `t' (throw) command is executed instead. Persistent.
- blind
- Start the character permanently blind (default false). Persis-
- tent.
- bones
- Allow saving and loading bones files (default true). Persis-
- tent.
- boulder
- Set the character used to display boulders (default is the
- "large rock" class symbol, ``').
- catname
- Name your starting cat (for example "catname:Morris"). Cannot
- be set with the `O' command.
- character
- Synonym for "role" to pick the type of your character (for ex-
- ample "character:Monk"). See role for more details.
- checkpoint
- Save game state after each level change, for possible recovery
- after program crash (default on). Persistent.
- checkspace
- Check free disk space before writing files to disk (default
- on). You may have to turn this off if you have more than 2 GB
- free space on the partition used for your save and level files
- (because too much space might overflow the calculation and end
- up looking like insufficient space). Only applies when MFLOPPY
- was defined during compilation.
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 52
+ NetHack Guidebook 49
- clicklook
- Allows looking at things on the screen by navigating the mouse
- over them and clicking the right mouse button (default off).
+ # Set your character's role, race, gender, and alignment.
+ OPTIONS=role:Valkyrie, race:Human, gender:female, align:lawful
+ #
+ # Turn on autopickup, set automatically picked up object types
+ OPTIONS=autopickup,pickup_types:$"=/!?+
+ #
+ # Map customization
+ OPTIONS=color # Display things in color if possible
+ OPTIONS=lit_corridor # Show lit corridors differently
+ OPTIONS=hilite_pet,hilite_pile
+ # Replace small punctuation (tick marks) with digits
+ SYMBOLS=S_boulder:0,S_golem:7
+ #
+ # No startup splash screen. Windows GUI only.
+ OPTIONS=!splash_screen
- cmdassist
- Have the game provide some additional command assistance for
- new players if it detects some anticipated mistakes (default
- on).
- confirm
- Have user confirm attacks on pets, shopkeepers, and other
- peaceable creatures (default on). Persistent.
- dark_room
- Show out-of-sight areas of lit rooms (default on). Persistent.
+ 9.3. Using the NETHACKOPTIONS environment variable
- disclose
- Controls what information the program reveals when the game
- ends. Value is a space separated list of prompting/category
- pairs (default is "ni na nv ng nc no", prompt with default re-
- sponse of `n' for each candidate). Persistent. The possibili-
- ties are:
+ The NETHACKOPTIONS variable is a comma-separated list of initial
+ values for the various options. Some can only be turned on or off.
+ You turn one of these on by adding the name of the option to the list,
+ and turn it off by typing a `!' or "no" before the name. Others take
+ a character string as a value. You can set string options by typing
+ the option name, a colon or equals sign, and then the value of the
+ string. The value is terminated by the next comma or the end of
+ string.
- i - disclose your inventory;
- a - disclose your attributes;
- v - summarize monsters that have been vanquished;
- g - list monster species that have been genocided;
- c - display your conduct;
- o - display dungeon overview.
+ For example, to set up an environment variable so that color is
+ on, legacy is off, character name is set to "Blue Meanie", and named
+ fruit is set to "lime", you would enter the command
- Each disclosure possibility can optionally be preceded by a
- prefix which lets you refine how it behaves. Here are the
- valid prefixes:
+ % setenv NETHACKOPTIONS "color,\!leg,name:Blue Meanie,fruit:lime"
- y - prompt you and default to yes on the prompt;
- n - prompt you and default to no on the prompt;
- + - disclose it without prompting;
- - - do not disclose it and do not prompt.
+ in csh (note the need to escape the `!' since it's special to that
+ shell), or the pair of commands
- The listing of vanquished monsters can be sorted, so there are
- two additional choices for `v':
+ $ NETHACKOPTIONS="color,!leg,name:Blue Meanie,fruit:lime"
+ $ export NETHACKOPTIONS
- ? - prompt you and default to ask on the prompt;
- # - disclose it without prompting, ask for sort order.
+ in sh, ksh, or bash.
- Asking refers to picking one of the orderings from a menu. The
- `+' disclose without prompting choice, or being prompted and
- answering `y' rather than `a', will default to showing monsters
- in the traditional order, from high level to low level.
+ The NETHACKOPTIONS value is effectively the same as a single
+ OPTIONS statement in a configuration file. The "OPTIONS=" prefix is
+ implied and comma separated options are processed from right to left.
+ Other types of configuration statements such as BIND or MSGTYPE are
+ not allowed.
- Omitted categories are implicitly added with `n' prefix. Spec-
- ified categories with omitted prefix implicitly use `+' prefix.
- Order of the disclosure categories does not matter, program
- display for end-of-game disclosure follows a set sequence.
+ Instead of a comma-separated list of options, NETHACKOPTIONS can
+ be set to the full name of a configuration file you want to use. If
+ that full name doesn't start with a slash, precede it with `@' (at-
+ sign) to let NetHack know that the rest is intended as a file name.
+ If it does start with `/', the at-sign is optional.
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 53
+ NetHack Guidebook 50
- (for example "disclose:yi na +v -g o") The example sets inven-
- tory to prompt and default to yes, attributes to prompt and de-
- fault to no, vanquished to disclose without prompting, genocid-
- ed to not disclose and not prompt, conduct to implicitly prompt
- and default to no, and overview to disclose without prompting.
+ 9.4. Customization options
- Note that the vanquished monsters list includes all monsters
- killed by traps and each other as well as by you. And the dun-
- geon overview shows all levels you had visited but does not re-
- veal things about them that you hadn't discovered.
+ Here are explanations of what the various options do. Character
+ strings that are too long may be truncated. Some of the options
+ listed may be inactive in your dungeon.
- dogname
- Name your starting dog (for example "dogname:Fang"). Cannot be
- set with the `O' command.
+ Some options are persistent, and are saved and reloaded along
+ with the game. Changing a persistent option in the configuration file
+ applies only to new games.
- extmenu
- Changes the extended commands interface to pop-up a menu of
- available commands. It is keystroke compatible with the tradi-
- tional interface except that it does not require that you hit
- Enter. It is implemented for the tty interface (default off).
+ acoustics
+ Enable messages about what your character hears (default on). Note
+ that this has nothing to do with your computer's audio capabilities.
+ Persistent.
- For the X11 interface, which always uses a menu for choosing an
- extended command, it controls whether the menu shows all avail-
- able commands (on) or just the subset of commands which have
- traditionally been considered extended ones (off).
+ align
+ Your starting alignment (align:lawful, align:neutral, or
+ align:chaotic). You may specify just the first letter. The default
+ is to randomly pick an appropriate alignment. If you prefix the
+ value with `!' or "no", you will exclude that alignment from being
+ picked randomly. Cannot be set with the `O' command. Persistent.
- female
- An obsolete synonym for "gender:female". Cannot be set with
- the `O' command.
+ autodescribe
+ Automatically describe the terrain under cursor when asked to get a
+ location on the map (default true). The whatis_coord option con-
+ trols whether the description includes map coordinates.
- fixinv
- An object's inventory letter sticks to it when it's dropped
- (default on). If this is off, dropping an object shifts all
- the remaining inventory letters. Persistent.
+ autodig
+ Automatically dig if you are wielding a digging tool and moving into
+ a place that can be dug (default false). Persistent.
- force_invmenu
- Commands asking for an inventory item show a menu instead of a
- text query with possible menu letters. Default is off.
+ autoopen
+ Walking into a door attempts to open it (default true). Persistent.
- fruit
- Name a fruit after something you enjoy eating (for example
- "fruit:mango") (default "slime mold"). Basically a nostalgic
- whimsy that NetHack uses from time to time. You should set
- this to something you find more appetizing than slime mold.
- Apples, oranges, pears, bananas, and melons already exist in
- NetHack, so don't use those.
+ autopickup
+ Automatically pick up things onto which you move (default on). Per-
+ sistent. See pickup_types to refine the behavior.
- gender
- Your starting gender (gender:male or gender:female). You may
- specify just the first letter. Although you can still denote
- your gender using the "male" and "female" options, the "gender"
- option will take precedence. The default is to randomly pick
- an appropriate gender. If you prefix the value with `!' or
- "no", you will exclude that gender from being picked randomly.
+ autoquiver
+ This option controls what happens when you attempt the `f' (fire)
+ command when nothing is quivered or readied (default false). When
+ true, the computer will fill your quiver or quiver sack or make
+ ready some suitable weapon. Note that it will not take into account
+ the blessed/cursed status, enchantment, damage, or quality of the
+ weapon; you are free to manually fill your quiver or quiver sack or
+ make ready with the `Q' command instead. If no weapon is found or
+ the option is false, the `t' (throw) command is executed instead.
+ Persistent.
+ blind
+ Start the character permanently blind (default false). Persistent.
- NetHack 3.6 March 4, 2020
+ bones
+ Allow saving and loading bones files (default true). Persistent.
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 54
+ NetHack Guidebook 51
- Cannot be set with the `O' command. Persistent.
- goldX
- When filtering objects based on bless/curse state (BUCX),
- whether to treat gold pieces as X (unknown bless/curse state,
- when "on") or U (known to be uncursed, when "off", the de-
- fault). Gold is never blessed or cursed, but it is not de-
- scribed as "uncursed" even when the implicit_uncursed option is
- "off".
- help
- If more information is available for an object looked at with
- the `/' command, ask if you want to see it (default on). Turn-
- ing help off makes just looking at things faster, since you
- aren't interrupted with the "More info?" prompt, but it also
- means that you might miss some interesting and/or important in-
- formation. Persistent.
+ boulder
+ Set the character used to display boulders (default is the "large
+ rock" class symbol, ``').
- herecmd_menu
- When using a windowport that supports mouse and clicking on
- yourself or next to you, show a menu of possible actions for
- the location. Same as "#herecmdmenu" and "#therecmdmenu" com-
- mands.
+ catname
+ Name your starting cat (for example "catname:Morris"). Cannot be
+ set with the `O' command.
- hilite_pet
- Visually distinguish pets from similar animals (default off).
- The behavior of this option depends on the type of windowing
- you use. In text windowing, text highlighting or inverse video
- is often used; with tiles, generally displays a heart symbol
- near pets.
+ character
+ Synonym for "role" to pick the type of your character (for example
+ "character:Monk"). See role for more details.
- With the curses interface, the petattr option controls how to
- highlight pets and setting it will turn the hilite_pet option
- on or off as warranted.
+ checkpoint
+ Save game state after each level change, for possible recovery after
+ program crash (default on). Persistent.
- hilite_pile
- Visually distinguish piles of objects from individual objects
- (default off). The behavior of this option depends on the type
- of windowing you use. In text windowing, text highlighting or
- inverse video is often used; with tiles, generally displays a
- small plus-symbol beside the object on the top of the pile.
+ checkspace
+ Check free disk space before writing files to disk (default on).
+ You may have to turn this off if you have more than 2 GB free space
+ on the partition used for your save and level files (because too
+ much space might overflow the calculation and end up looking like
+ insufficient space). Only applies when MFLOPPY was defined during
+ compilation.
- hitpointbar
- Show a hit point bar graph behind your name and title. Only
- available for TTY and Windows GUI, and only when statushilites
- is on.
+ clicklook
+ Allows looking at things on the screen by navigating the mouse over
+ them and clicking the right mouse button (default off).
- horsename
- Name your starting horse (for example "horsename:Trigger").
- Cannot be set with the `O' command.
+ cmdassist
+ Have the game provide some additional command assistance for new
+ players if it detects some anticipated mistakes (default on).
- ignintr
- Ignore interrupt signals, including breaks (default off). Per-
- sistent.
+ confirm
+ Have user confirm attacks on pets, shopkeepers, and other peaceable
+ creatures (default on). Persistent.
+ dark_room
+ Show out-of-sight areas of lit rooms (default on). Persistent.
- NetHack 3.6 March 4, 2020
+ disclose
+ Controls what information the program reveals when the game ends.
+ Value is a space separated list of prompting/category pairs (default
+ is "ni na nv ng nc no", prompt with default response of `n' for each
+ candidate). Persistent. The possibilities are:
+ i - disclose your inventory;
+ a - disclose your attributes;
+ v - summarize monsters that have been vanquished;
+ g - list monster species that have been genocided;
+ c - display your conduct;
+ o - display dungeon overview.
+ Each disclosure possibility can optionally be preceded by a prefix
+ which lets you refine how it behaves. Here are the valid prefixes:
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 55
- implicit_uncursed
- Omit "uncursed" from inventory lists, if possible (default on).
- legacy
- Display an introductory message when starting the game (default
- on). Persistent.
+ NetHack Guidebook 52
- lit_corridor
- Show corridor squares seen by night vision or a light source
- held by your character as lit (default off). Persistent.
- lootabc
- When using a menu to interact with a container, use the old
- `a', `b', and `c' keyboard shortcuts rather than the mnemonics
- `o', `i', and `b' (default off). Persistent.
- mail
- Enable mail delivery during the game (default on). Persistent.
+ y - prompt you and default to yes on the prompt;
+ n - prompt you and default to no on the prompt;
+ + - disclose it without prompting;
+ - - do not disclose it and do not prompt.
- male
- An obsolete synonym for "gender:male". Cannot be set with the
- `O' command.
+ The listing of vanquished monsters can be sorted, so there are two
+ additional choices for `v':
- mention_walls
- Give feedback when walking against a wall (default off).
+ ? - prompt you and default to ask on the prompt;
+ # - disclose it without prompting, ask for sort order.
- menucolors
- Enable coloring menu lines (default off). See "Configuring
- Menu Colors" on how to configure the colors.
+ Asking refers to picking one of the orderings from a menu. The `+'
+ disclose without prompting choice, or being prompted and answering
+ `y' rather than `a', will default to showing monsters in the tradi-
+ tional order, from high level to low level.
- menustyle
- Controls the interface used when you need to choose various ob-
- jects (in response to the Drop command, for instance). The
- value specified should be the first letter of one of the fol-
- lowing: traditional, combination, full, or partial. Tradi-
- tional was the only interface available for early versions; it
- consists of a prompt for object class characters, followed by
- an object-by-object prompt for all items matching the selected
- object class(es). Combination starts with a prompt for object
- class(es) of interest, but then displays a menu of matching ob-
- jects rather than prompting one-by-one. Full displays a menu
- of object classes rather than a character prompt, and then a
- menu of matching objects for selection. Partial skips the ob-
- ject class filtering and immediately displays a menu of all ob-
- jects. Persistent.
+ Omitted categories are implicitly added with `n' prefix. Specified
+ categories with omitted prefix implicitly use `+' prefix. Order of
+ the disclosure categories does not matter, program display for end-
+ of-game disclosure follows a set sequence.
- menu_deselect_all
- Menu character accelerator to deselect all items in a menu.
- Implemented by the Amiga, Gem, X11 and tty ports. Default `-'.
+ (for example "disclose:yi na +v -g o") The example sets inventory to
+ prompt and default to yes, attributes to prompt and default to no,
+ vanquished to disclose without prompting, genocided to not disclose
+ and not prompt, conduct to implicitly prompt and default to no, and
+ overview to disclose without prompting.
- menu_deselect_page
- Menu character accelerator to deselect all items on this page
- of a menu. Implemented by the Amiga, Gem and tty ports. De-
- fault `\'.
+ Note that the vanquished monsters list includes all monsters killed
+ by traps and each other as well as by you. And the dungeon overview
+ shows all levels you had visited but does not reveal things about
+ them that you hadn't discovered.
+ dogname
+ Name your starting dog (for example "dogname:Fang"). Cannot be set
+ with the `O' command.
- NetHack 3.6 March 4, 2020
+ extmenu
+ Changes the extended commands interface to pop-up a menu of avail-
+ able commands. It is keystroke compatible with the traditional
+ interface except that it does not require that you hit Enter. It is
+ implemented for the tty interface (default off).
+ For the X11 interface, which always uses a menu for choosing an
+ extended command, it controls whether the menu shows all available
+ commands (on) or just the subset of commands which have tradition-
+ ally been considered extended ones (off).
+ female
+ An obsolete synonym for "gender:female". Cannot be set with the `O'
+ command.
+ fixinv
+ An object's inventory letter sticks to it when it's dropped (default
+ on). If this is off, dropping an object shifts all the remaining
- NetHack Guidebook 56
+ NetHack 3.6.7 February 3, 2023
- menu_first_page
- Menu character accelerator to jump to the first page in a menu.
- Implemented by the Amiga, Gem and tty ports. Default `^'.
- menu_headings
- Controls how the headings in a menu are highlighted. Values
- are "none", "bold", "dim", "underline", "blink", or "inverse".
- Not all ports can actually display all types.
- menu_invert_all
- Menu character accelerator to invert all items in a menu. Im-
- plemented by the Amiga, Gem, X11 and tty ports. Default `@'.
+ NetHack Guidebook 53
- menu_invert_page
- Menu character accelerator to invert all items on this page of
- a menu. Implemented by the Amiga, Gem and tty ports. Default
- `~'.
- menu_last_page
- Menu character accelerator to jump to the last page in a menu.
- Implemented by the Amiga, Gem and tty ports. Default `|'.
- menu_next_page
- Menu character accelerator to goto the next menu page. Imple-
- mented by the Amiga, Gem and tty ports. Default `>'.
+ inventory letters. Persistent.
- menu_objsyms
- Show object symbols in menu headings in menus where the object
- symbols act as menu accelerators (default off).
+ force_invmenu
+ Commands asking for an inventory item show a menu instead of a text
+ query with possible menu letters. Default is off.
- menu_overlay
- Do not clear the screen before drawing menus, and align menus
- to the right edge of the screen. Only for the tty port. (de-
- fault on)
+ fruit
+ Name a fruit after something you enjoy eating (for example
+ "fruit:mango") (default "slime mold"). Basically a nostalgic whimsy
+ that NetHack uses from time to time. You should set this to some-
+ thing you find more appetizing than slime mold. Apples, oranges,
+ pears, bananas, and melons already exist in NetHack, so don't use
+ those.
- menu_previous_page
- Menu character accelerator to goto the previous menu page. Im-
- plemented by the Amiga, Gem and tty ports. Default `<'.
+ gender
+ Your starting gender (gender:male or gender:female). You may spec-
+ ify just the first letter. Although you can still denote your gen-
+ der using the "male" and "female" options, the "gender" option will
+ take precedence. The default is to randomly pick an appropriate
+ gender. If you prefix the value with `!' or "no", you will exclude
+ that gender from being picked randomly. Cannot be set with the `O'
+ command. Persistent.
- menu_search
- Menu character accelerator to search for a menu item. Imple-
- mented by the Amiga, Gem, X11 and tty ports. Default `:'.
+ goldX
+ When filtering objects based on bless/curse state (BUCX), whether to
+ treat gold pieces as X (unknown bless/curse state, when "on") or U
+ (known to be uncursed, when "off", the default). Gold is never
+ blessed or cursed, but it is not described as "uncursed" even when
+ the implicit_uncursed option is "off".
- menu_select_all
- Menu character accelerator to select all items in a menu. Im-
- plemented by the Amiga, Gem, X11 and tty ports. Default `.'.
+ help
+ If more information is available for an object looked at with the
+ `/' command, ask if you want to see it (default on). Turning help
+ off makes just looking at things faster, since you aren't inter-
+ rupted with the "More info?" prompt, but it also means that you
+ might miss some interesting and/or important information. Persis-
+ tent.
- menu_select_page
- Menu character accelerator to select all items on this page of
- a menu. Implemented by the Amiga, Gem and tty ports. Default
- `,'.
+ herecmd_menu
+ When using a windowport that supports mouse and clicking on yourself
+ or next to you, show a menu of possible actions for the location.
+ Same as "#herecmdmenu" and "#therecmdmenu" commands.
- monpolycontrol
- Prompt for new form whenever any monster changes shape (default
+ hilite_pet
+ Visually distinguish pets from similar animals (default off). The
+ behavior of this option depends on the type of windowing you use.
+ In text windowing, text highlighting or inverse video is often used;
+ with tiles, generally displays a heart symbol near pets.
+ With the curses interface, the petattr option controls how to high-
+ light pets and setting it will turn the hilite_pet option on or off
+ as warranted.
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 57
- off). Debug mode only.
+ NetHack Guidebook 54
- mouse_support
- Allow use of the mouse for input and travel. Valid settings
- are:
- 0 - disabled
- 1 - enabled and make OS adjustments to support mouse use
- 2 - like 1 but does not make any OS adjustments
- Omitting a value is the same as specifying 1 and negating
- mouse_support is the same as specifying 0.
+ hilite_pile
+ Visually distinguish piles of objects from individual objects
+ (default off). The behavior of this option depends on the type of
+ windowing you use. In text windowing, text highlighting or inverse
+ video is often used; with tiles, generally displays a small plus-
+ symbol beside the object on the top of the pile.
- msghistory
- The number of top line messages to keep (and be able to recall
- with `^P') (default 20). Cannot be set with the `O' command.
+ hitpointbar
+ Show a hit point bar graph behind your name and title. Only avail-
+ able for TTY and Windows GUI, and only when statushilites is on.
- msg_window
- Allows you to change the way recalled messages are displayed.
- Currently it is only supported for tty (all four choices) and
- for curses (`f' and `r' choices, default `r'). The possible
- values are:
+ horsename
+ Name your starting horse (for example "horsename:Trigger"). Cannot
+ be set with the `O' command.
- s - single message (default; only choice prior to 3.4.0);
- c - combination, two messages as "single", then as "full";
- f - full window, oldest message first;
- r - full window reversed, newest message first.
+ ignintr
+ Ignore interrupt signals, including breaks (default off). Persis-
+ tent.
- For backward compatibility, no value needs to be specified
- (which defaults to "full"), or it can be negated (which
- defaults to "single").
+ implicit_uncursed
+ Omit "uncursed" from inventory lists, if possible (default on).
- name
- Set your character's name (defaults to your user name). You
- can also set your character's role by appending a dash and one
- or more letters of the role (that is, by suffixing one of -A -B
- -C -H -K -M -P -Ra -Ro -S -T -V -W). If -@ is used for the
- role, then a random one will be automatically chosen. Cannot
- be set with the `O' command.
+ legacy
+ Display an introductory message when starting the game (default on).
+ Persistent.
- news
- Read the NetHack news file, if present (default on). Since the
- news is shown at the beginning of the game, there's no point in
- setting this with the `O' command.
+ lit_corridor
+ Show corridor squares seen by night vision or a light source held by
+ your character as lit (default off). Persistent.
- nudist
- Start the character with no armor (default false). Persistent.
+ lootabc
+ When using a menu to interact with a container, use the old `a',
+ `b', and `c' keyboard shortcuts rather than the mnemonics `o', `i',
+ and `b' (default off). Persistent.
- null
- Send padding nulls to the terminal (default on). Persistent.
+ mail
+ Enable mail delivery during the game (default on). Persistent.
- number_pad
- Use digit keys instead of letters to move (default 0 or off).
- Valid settings are:
+ male
+ An obsolete synonym for "gender:male". Cannot be set with the `O'
+ command.
+ mention_walls
+ Give feedback when walking against a wall (default off).
- NetHack 3.6 March 4, 2020
+ menucolors
+ Enable coloring menu lines (default off). See "Configuring Menu
+ Colors" on how to configure the colors.
+ menustyle
+ Controls the interface used when you need to choose various objects
+ (in response to the Drop command, for instance). The value speci-
+ fied should be the first letter of one of the following: tradi-
+ tional, combination, full, or partial. Traditional was the only
+ NetHack 3.6.7 February 3, 2023
- NetHack Guidebook 58
- 0 - move by letters; "yuhjklbn"
- 1 - move by numbers; digit `5' acts as `G' movement prefix
- 2 - like 1 but `5' works as `g' prefix instead of as `G'
- 3 - by numbers using phone key layout; 123 above, 789 below
- 4 - combines 3 with 2; phone layout plus MS-DOS compatibility
- -1 - by letters but use `z' to go northwest, `y' to zap wands
+ NetHack Guidebook 55
- For backward compatibility, omitting a value is the same as
- specifying 1 and negating number_pad is the same as specifying
- 0. (Settings 2 and 4 are for compatibility with MS-DOS or old
- PC Hack; in addition to the different behavior for `5', `Alt-5'
- acts as `G' and `Alt-0' acts as `I'. Setting -1 is to accommo-
- date some QWERTZ keyboards which have the location of the `y'
- and `z' keys swapped.) When moving by numbers, to enter a
- count prefix for those commands which accept one (such as "12s"
- to search twelve times), precede it with the letter `n'
- ("n12s").
- packorder
- Specify the order to list object types in (default
- "")[%?+!=/(*`0_"). The value of this option should be a string
- containing the symbols for the various object types. Any omit-
- ted types are filled in at the end from the previous order.
- paranoid_confirmation
- A space separated list of specific situations where alternate
- prompting is desired. The default is paranoid_confirma-
- tion:pray.
+ interface available for early versions; it consists of a prompt for
+ object class characters, followed by an object-by-object prompt for
+ all items matching the selected object class(es). Combination
+ starts with a prompt for object class(es) of interest, but then dis-
+ plays a menu of matching objects rather than prompting one-by-one.
+ Full displays a menu of object classes rather than a character
+ prompt, and then a menu of matching objects for selection. Partial
+ skips the object class filtering and immediately displays a menu of
+ all objects. Persistent.
- Confirm - for any prompts which are set to require "yes"
- rather than `y', also require "no" to reject in-
- stead of accepting any non-yes response as no
- quit - require "yes" rather than `y' to confirm quitting
- the game or switching into non-scoring explore
- mode;
- die - require "yes" rather than `y' to confirm dying
- (not useful in normal play; applies to explore
- mode);
- bones - require "yes" rather than `y' to confirm saving
- bones data when dying in debug mode;
- attack - require "yes" rather than `y' to confirm attack-
- ing a peaceful monster;
- wand-break - require "yes" rather than `y' to confirm breaking
- a wand;
- eating - require "yes" rather than `y' to confirm whether
- to continue eating;
- Were-change - require "yes" rather than `y' to confirm changing
- form due to lycanthropy when hero has polymorph
- control;
- pray - require `y' to confirm an attempt to pray rather
- than immediately praying; on by default;
- Remove - require selection from inventory for `R' and `T'
- commands even when wearing just one applicable
- item.
+ menu_deselect_all
+ Menu character accelerator to deselect all items in a menu. Imple-
+ mented by the Amiga, Gem, X11 and tty ports. Default `-'.
+ menu_deselect_page
+ Menu character accelerator to deselect all items on this page of a
+ menu. Implemented by the Amiga, Gem and tty ports. Default `\'.
- NetHack 3.6 March 4, 2020
+ menu_first_page
+ Menu character accelerator to jump to the first page in a menu.
+ Implemented by the Amiga, Gem and tty ports. Default `^'.
+ menu_headings
+ Controls how the headings in a menu are highlighted. Values are
+ "none", "bold", "dim", "underline", "blink", or "inverse". Not all
+ ports can actually display all types.
+ menu_invert_all
+ Menu character accelerator to invert all items in a menu. Imple-
+ mented by the Amiga, Gem, X11 and tty ports. Default `@'.
+ menu_invert_page
+ Menu character accelerator to invert all items on this page of a
+ menu. Implemented by the Amiga, Gem and tty ports. Default `~'.
+ menu_last_page
+ Menu character accelerator to jump to the last page in a menu.
+ Implemented by the Amiga, Gem and tty ports. Default `|'.
- NetHack Guidebook 59
+ menu_next_page
+ Menu character accelerator to goto the next menu page. Implemented
+ by the Amiga, Gem and tty ports. Default `>'.
+ menu_objsyms
+ Show object symbols in menu headings in menus where the object sym-
+ bols act as menu accelerators (default off).
+ menu_overlay
+ Do not clear the screen before drawing menus, and align menus to the
+ right edge of the screen. Only for the tty port. (default on)
- all - turn on all of the above.
+ menu_previous_page
+ Menu character accelerator to goto the previous menu page. Imple-
+ mented by the Amiga, Gem and tty ports. Default `<'.
- By default, the pray choice is enabled, the others disabled.
- To disable it without setting any of the other choices, use
- "paranoid_confirmation:none". To keep it enabled while setting
- any of the others, include it in the list, such as "para-
- noid_confirmation:attack pray Remove".
- perm_invent
- If true, always display your current inventory in a window.
- This only makes sense for windowing system interfaces that im-
- plement this feature.
+ NetHack 3.6.7 February 3, 2023
- petattr
- Specifies one or more text highlighting attributes to use when
- showing pets on the map. Effectively a superset of the
- hilite_pet boolean option. Curses interface only; value is one
- or more of the following letters.
- n - Normal text (no highlighting)
- i - Inverse video (default)
- b - Bold text
- u - Underlined text
- k - blinKing text
- d - Dim text
- t - iTalic text
- l - Left line indicator
- r - Right line indicator
- Some of those choices might not work, particularly the final
- three, depending upon terminal hardware or terminal emulation
- software.
- Currently multiple highlight-style letters can be combined by
- simply stringing them together (for example, "bk"), but in the
- future they might require being separated by plus signs (such
- as "b+k", which works already). When using the `n' choice, it
- should be specified on its own, not in combination with any of
- the other letters.
- pettype
- Specify the type of your initial pet, if you are playing a
- character class that uses multiple types of pets; or choose to
- have no initial pet at all. Possible values are "cat", "dog",
- "horse", and "none". If the choice is not allowed for the role
- you are currently playing, it will be silently ignored. For
- example, "horse" will only be honored when playing a knight.
- Cannot be set with the `O' command.
+ NetHack Guidebook 56
- pickup_burden
- When you pick up an item that would exceed this encumbrance
- level (Unencumbered, Burdened, streSsed, straiNed, overTaxed,
- or overLoaded), you will be asked if you want to continue.
- (Default `S'). Persistent.
- NetHack 3.6 March 4, 2020
+ menu_search
+ Menu character accelerator to search for a menu item. Implemented
+ by the Amiga, Gem, X11 and tty ports. Default `:'.
+ menu_select_all
+ Menu character accelerator to select all items in a menu. Imple-
+ mented by the Amiga, Gem, X11 and tty ports. Default `.'.
+ menu_select_page
+ Menu character accelerator to select all items on this page of a
+ menu. Implemented by the Amiga, Gem and tty ports. Default `,'.
+ monpolycontrol
+ Prompt for new form whenever any monster changes shape (default
+ off). Debug mode only.
+ mouse_support
+ Allow use of the mouse for input and travel. Valid settings are:
- NetHack Guidebook 60
+ 0 - disabled
+ 1 - enabled and make OS adjustments to support mouse use
+ 2 - like 1 but does not make any OS adjustments
+ Omitting a value is the same as specifying 1 and negating mouse_sup-
+ port is the same as specifying 0.
+ msghistory
+ The number of top line messages to keep (and be able to recall with
+ `^P') (default 20). Cannot be set with the `O' command.
- pickup_thrown
- If this option is on and autopickup is also on, try to pick up
- things that you threw, even if they aren't in pickup_types or
- match an autopickup exception. Default is on. Persistent.
+ msg_window
+ Allows you to change the way recalled messages are displayed. Cur-
+ rently it is only supported for tty (all four choices) and for
+ curses (`f' and `r' choices, default `r'). The possible values are:
- pickup_types
- Specify the object types to be picked up when autopickup is on.
- Default is all types. You can use autopickup_exception config-
- uration file lines to further refine autopickup behavior. Per-
- sistent.
+ s - single message (default; only choice prior to 3.4.0);
+ c - combination, two messages as "single", then as "full";
+ f - full window, oldest message first;
+ r - full window reversed, newest message first.
- pile_limit
- When walking across a pile of objects on the floor, threshold
- at which the message "there are few/several/many objects here"
- is given instead of showing a popup list of those objects. A
- value of 0 means "no limit" (always list the objects); a value
- of 1 effectively means "never show the objects" since the pile
- size will always be at least that big; default value is 5.
- Persistent.
+ For backward compatibility, no value needs to be specified (which
+ defaults to "full"), or it can be negated (which defaults to "sin-
+ gle").
- playmode
- Values are "normal", "explore", or "debug". Allows selection
- of explore mode (also known as discovery mode) or debug mode
- (also known as wizard mode) instead of normal play. Debug mode
- might only be allowed for someone logged in under a particular
- user name (on multi-user systems) or specifying a particular
- character name (on single-user systems) or it might be disabled
- entirely. Requesting it when not allowed or not possible re-
- sults in explore mode instead. Default is normal play.
+ name
+ Set your character's name (defaults to your user name). You can
+ also set your character's role by appending a dash and one or more
+ letters of the role (that is, by suffixing one of -A -B -C -H -K -M
+ -P -Ra -Ro -S -T -V -W). If -@ is used for the role, then a random
+ one will be automatically chosen. Cannot be set with the `O' com-
+ mand.
- pushweapon
- Using the `w' (wield) command when already wielding something
- pushes the old item into your alternate weapon slot (default
- off). Likewise for the `a' (apply) command if it causes the
- applied item to become wielded. Persistent.
+ news
+ Read the NetHack news file, if present (default on). Since the news
- race
- Selects your race (for example, "race:human"). Default is ran-
- dom. If you prefix the value with `!' or "no", you will ex-
- clude that race from being picked randomly. Cannot be set with
- the `O' command. Persistent.
- rest_on_space
- Make the space bar a synonym for the `.' (#wait) command (de-
- fault off). Persistent.
+ NetHack 3.6.7 February 3, 2023
- role
- Pick your type of character (for example "role:Samurai"); syn-
- onym for "character". See "name" for an alternate method of
- specifying your role. Normally only the first letter of the
- value is examined; `r' is an exception with "Rogue", "Ranger",
- and "random" values. If you prefix the value with `!' or "no",
- you will exclude that role from being picked randomly. Cannot
- be set with the `O' command. Persistent.
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 57
- NetHack Guidebook 61
+ is shown at the beginning of the game, there's no point in setting
+ this with the `O' command.
+ nudist
+ Start the character with no armor (default false). Persistent.
+ null
+ Send padding nulls to the terminal (default on). Persistent.
- roguesymset
- This option may be used to select one of the named symbol sets
- found within "symbols" to alter the symbols displayed on the
- screen on the rogue level.
+ number_pad
+ Use digit keys instead of letters to move (default 0 or off). Valid
+ settings are:
- rlecomp
- When writing out a save file, perform run length compression of
- the map. Not all ports support run length compression. It has
- no effect on reading an existing save file.
+ 0 - move by letters; "yuhjklbn"
+ 1 - move by numbers; digit `5' acts as `G' movement prefix
+ 2 - like 1 but `5' works as `g' prefix instead of as `G'
+ 3 - by numbers using phone key layout; 123 above, 789 below
+ 4 - combines 3 with 2; phone layout plus MS-DOS compatibility
+ -1 - by letters but use `z' to go northwest, `y' to zap wands
- runmode
- Controls the amount of screen updating for the map window when
- engaged in multi-turn movement (running via shift+direction or
- control+direction and so forth, or via the travel command or
- mouse click). The possible values are:
+ For backward compatibility, omitting a value is the same as specify-
+ ing 1 and negating number_pad is the same as specifying 0. (Set-
+ tings 2 and 4 are for compatibility with MS-DOS or old PC Hack; in
+ addition to the different behavior for `5', `Alt-5' acts as `G' and
+ `Alt-0' acts as `I'. Setting -1 is to accommodate some QWERTZ key-
+ boards which have the location of the `y' and `z' keys swapped.)
+ When moving by numbers, to enter a count prefix for those commands
+ which accept one (such as "12s" to search twelve times), precede it
+ with the letter `n' ("n12s").
- teleport - update the map after movement has finished;
- run - update the map after every seven or so steps;
- walk - update the map after each step;
- crawl - like walk, but pause briefly after each step.
+ packorder
+ Specify the order to list object types in (default
+ "")[%?+!=/(*`0_"). The value of this option should be a string con-
+ taining the symbols for the various object types. Any omitted types
+ are filled in at the end from the previous order.
- This option only affects the game's screen display, not the ac-
- tual results of moving. The default is "run"; versions prior
- to 3.4.1 used "teleport" only. Whether or not the effect is
- noticeable will depend upon the window port used or on the type
- of terminal. Persistent.
+ paranoid_confirmation
+ A space separated list of specific situations where alternate
+ prompting is desired. The default is paranoid_confirmation:pray.
- safe_pet
- Prevent you from (knowingly) attacking your pets (default on).
- Persistent.
+ Confirm - for any prompts which are set to require "yes" rather
+ than `y', also require "no" to reject instead of
+ accepting any non-yes response as no
+ quit - require "yes" rather than `y' to confirm quitting the
+ game or switching into non-scoring explore mode;
+ die - require "yes" rather than `y' to confirm dying (not
+ useful in normal play; applies to explore mode);
+ bones - require "yes" rather than `y' to confirm saving bones
+ data when dying in debug mode;
+ attack - require "yes" rather than `y' to confirm attacking a
+ peaceful monster;
+ wand-break - require "yes" rather than `y' to confirm breaking a
+ wand;
+ eating - require "yes" rather than `y' to confirm whether to
- sanity_check
- Evaluate monsters, objects, and map prior to each turn (default
- off). Debug mode only.
- scores
- Control what parts of the score list you are shown at the end
- (for example "scores:5 top scores/4 around my score/own
- scores"). Only the first letter of each category (`t', `a', or
- `o') is necessary. Persistent.
+ NetHack 3.6.7 February 3, 2023
- showexp
- Show your accumulated experience points on bottom line (default
- off). Persistent.
- showrace
- Display yourself as the glyph for your race, rather than the
- glyph for your role (default off). Note that this setting af-
- fects only the appearance of the display, not the way the game
- treats you. Persistent.
- showscore
- Show your approximate accumulated score on bottom line (default
- off). Persistent.
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 58
+ continue eating;
+ Were-change - require "yes" rather than `y' to confirm changing form
+ due to lycanthropy when hero has polymorph control;
+ pray - require `y' to confirm an attempt to pray rather than
+ immediately praying; on by default;
+ Remove - require selection from inventory for `R' and `T' com-
+ mands even when wearing just one applicable item.
+ all - turn on all of the above.
+ By default, the pray choice is enabled, the others disabled. To
+ disable it without setting any of the other choices, use "para-
+ noid_confirmation:none". To keep it enabled while setting any of
+ the others, include it in the list, such as "paranoid_confirma-
+ tion:attack pray Remove".
- NetHack Guidebook 62
+ perm_invent
+ If true, always display your current inventory in a window. This
+ only makes sense for windowing system interfaces that implement this
+ feature.
+ petattr
+ Specifies one or more text highlighting attributes to use when show-
+ ing pets on the map. Effectively a superset of the hilite_pet bool-
+ ean option. Curses interface only; value is one or more of the fol-
+ lowing letters.
+ n - Normal text (no highlighting)
+ i - Inverse video (default)
+ b - Bold text
+ u - Underlined text
+ k - blinKing text
+ d - Dim text
+ t - iTalic text
+ l - Left line indicator
+ r - Right line indicator
- silent
- Suppress terminal beeps (default on). Persistent.
+ Some of those choices might not work, particularly the final three,
+ depending upon terminal hardware or terminal emulation software.
- sortloot
- Controls the sorting behavior of the pickup lists for inventory
- and #loot commands and some others. Persistent. The possible
- values are:
+ Currently multiple highlight-style letters can be combined by simply
+ stringing them together (for example, "bk"), but in the future they
+ might require being separated by plus signs (such as "b+k", which
+ works already). When using the `n' choice, it should be specified
+ on its own, not in combination with any of the other letters.
- full - always sort the lists;
- loot - only sort the lists that don't use inventory letters,
- like with the #loot and pickup commands;
- none - show lists the traditional way without sorting.
+ pettype
+ Specify the type of your initial pet, if you are playing a character
+ class that uses multiple types of pets; or choose to have no initial
+ pet at all. Possible values are "cat", "dog", "horse", and "none".
+ If the choice is not allowed for the role you are currently playing,
+ it will be silently ignored. For example, "horse" will only be hon-
+ ored when playing a knight. Cannot be set with the `O' command.
- sortpack
- Sort the pack contents by type when displaying inventory (de-
- fault on). Persistent.
- sparkle
- Display a sparkly effect when a monster (including yourself) is
- hit by an attack to which it is resistant (default on). Per-
- sistent.
- standout
- Boldface monsters and "--More--" (default off). Persistent.
- statushilites
- Controls how many turns status hilite behaviors highlight the
- field. If negated or set to zero, disables status hiliting.
- See "Configuring Status Hilites" for further information.
+ NetHack 3.6.7 February 3, 2023
- status_updates
- Allow updates to the status lines at the bottom of the screen
- (default true).
- suppress_alert
- This option may be set to a NetHack version level to suppress
- alert notification messages about feature changes for that and
- prior versions (for example "suppress_alert:3.3.1").
- symset
- This option may be used to select one of the named symbol sets
- found within "symbols" to alter the symbols displayed on the
- screen. Use "symset:default" to explicitly select the default
- symbols.
- time
- Show the elapsed game time in turns on bottom line (default
- off). Persistent.
- timed_delay
- When pausing momentarily for display effect, such as with ex-
- plosions and moving objects, use a timer rather than sending
- extra characters to the screen. (Applies to "tty" interface
- only; "X11" interface always uses a timer based delay. The
+ NetHack Guidebook 59
- NetHack 3.6 March 4, 2020
+ pickup_burden
+ When you pick up an item that would exceed this encumbrance level
+ (Unencumbered, Burdened, streSsed, straiNed, overTaxed, or over-
+ Loaded), you will be asked if you want to continue. (Default `S').
+ Persistent.
+ pickup_thrown
+ If this option is on and autopickup is also on, try to pick up
+ things that you threw, even if they aren't in pickup_types or match
+ an autopickup exception. Default is on. Persistent.
+ pickup_types
+ Specify the object types to be picked up when autopickup is on.
+ Default is all types. You can use autopickup_exception configura-
+ tion file lines to further refine autopickup behavior. Persistent.
+ pile_limit
+ When walking across a pile of objects on the floor, threshold at
+ which the message "there are few/several/many objects here" is given
+ instead of showing a popup list of those objects. A value of 0
+ means "no limit" (always list the objects); a value of 1 effectively
+ means "never show the objects" since the pile size will always be at
+ least that big; default value is 5. Persistent.
- NetHack Guidebook 63
+ playmode
+ Values are "normal", "explore", or "debug". Allows selection of
+ explore mode (also known as discovery mode) or debug mode (also
+ known as wizard mode) instead of normal play. Debug mode might only
+ be allowed for someone logged in under a particular user name (on
+ multi-user systems) or specifying a particular character name (on
+ single-user systems) or it might be disabled entirely. Requesting
+ it when not allowed or not possible results in explore mode instead.
+ Default is normal play.
+ pushweapon
+ Using the `w' (wield) command when already wielding something pushes
+ the old item into your alternate weapon slot (default off). Like-
+ wise for the `a' (apply) command if it causes the applied item to
+ become wielded. Persistent.
+ race
+ Selects your race (for example, "race:human"). Default is random.
+ If you prefix the value with `!' or "no", you will exclude that race
+ from being picked randomly. Cannot be set with the `O' command.
+ Persistent.
- default is on if configured into the program.) Persistent.
+ rest_on_space
+ Make the space bar a synonym for the `.' (#wait) command (default
+ off). Persistent.
- tombstone
- Draw a tombstone graphic upon your death (default on). Persis-
- tent.
+ role
+ Pick your type of character (for example "role:Samurai"); synonym
+ for "character". See "name" for an alternate method of specifying
+ your role. Normally only the first letter of the value is examined;
- toptenwin
- Put the ending display in a NetHack window instead of on stdout
- (default off). Setting this option makes the score list visi-
- ble when a windowing version of NetHack is started without a
- parent window, but it no longer leaves the score list around
- after game end on a terminal or emulating window.
- travel
- Allow the travel command (default on). Turning this option off
- will prevent the game from attempting unintended moves if you
- make inadvertent mouse clicks on the map window. Persistent.
+ NetHack 3.6.7 February 3, 2023
- verbose
- Provide more commentary during the game (default on). Persis-
- tent.
- whatis_coord
- When using the `/' or `;' commands to look around on the map
- with autodescribe on, display coordinates after the descrip-
- tion. Also works in other situations where you are asked to
- pick a location.
- The possible settings are:
- c - compass ("east" or "3s" or "2n,4w");
- f - full compass ("east" or "3south" or "2north,4west");
- m - map (map column x=0 is not used);
- s - screen [row,column] (row is offset to match tty usage);
- n - none (no coordinates shown) [default].
- The whatis_coord option is also used with the "/m", "/M", "/o",
- and "/O" sub-commands of `/', where the "none" setting is over-
- ridden with "map".
+ NetHack Guidebook 60
- whatis_filter
- When getting a location on the map, and using the keys to cycle
- through next and previous targets, allows filtering the possi-
- ble targets.
- n - no filtering [default]
- v - in view only
- a - in same area only
- The area-filter tries to be slightly predictive -- if you're
- standing on a doorway, it will consider the area on the side of
- the door you were last moving towards.
+ `r' is an exception with "Rogue", "Ranger", and "random" values. If
+ you prefix the value with `!' or "no", you will exclude that role
+ from being picked randomly. Cannot be set with the `O' command.
+ Persistent.
+ roguesymset
+ This option may be used to select one of the named symbol sets found
+ within "symbols" to alter the symbols displayed on the screen on the
+ rogue level.
+ rlecomp
+ When writing out a save file, perform run length compression of the
+ map. Not all ports support run length compression. It has no effect
+ on reading an existing save file.
+ runmode
+ Controls the amount of screen updating for the map window when
+ engaged in multi-turn movement (running via shift+direction or con-
+ trol+direction and so forth, or via the travel command or mouse
+ click). The possible values are:
- NetHack 3.6 March 4, 2020
+ teleport - update the map after movement has finished;
+ run - update the map after every seven or so steps;
+ walk - update the map after each step;
+ crawl - like walk, but pause briefly after each step.
+ This option only affects the game's screen display, not the actual
+ results of moving. The default is "run"; versions prior to 3.4.1
+ used "teleport" only. Whether or not the effect is noticeable will
+ depend upon the window port used or on the type of terminal. Per-
+ sistent.
+ safe_pet
+ Prevent you from (knowingly) attacking your pets (default on). Per-
+ sistent.
+ sanity_check
+ Evaluate monsters, objects, and map prior to each turn (default
+ off). Debug mode only.
+ scores
+ Control what parts of the score list you are shown at the end (for
+ example "scores:5 top scores/4 around my score/own scores"). Only
+ the first letter of each category (`t', `a', or `o') is necessary.
+ Persistent.
- NetHack Guidebook 64
+ showexp
+ Show your accumulated experience points on bottom line (default
+ off). Persistent.
+ showrace
+ Display yourself as the glyph for your race, rather than the glyph
+ for your role (default off). Note that this setting affects only
+ the appearance of the display, not the way the game treats you.
- Filtering can also be changed when getting a location with the
- "getpos.filter" key.
+ NetHack 3.6.7 February 3, 2023
- whatis_menu
- When getting a location on the map, and using a key to cycle
- through next and previous targets, use a menu instead to pick a
- target. (default off)
- whatis_moveskip
- When getting a location on the map, and using shifted movement
- keys or meta-digit keys to fast-move, instead of moving 8 units
- at a time, move by skipping the same glyphs. (default off)
- windowtype
- When the program has been built to support multiple interfaces,
- select which one to use, such as "tty" or "X11" (default de-
- pends on build-time settings; use "#version" to check). Cannot
- be set with the `O' command.
- When used, it should be the first option set since its value
- might enable or disable the availability of various other op-
- tions. For multiple lines in a configuration file, that would
- be the first non-comment line. For a comma-separated list in
- NETHACKOPTIONS or an OPTIONS line in a configuration file, that
- would be the rightmost option in the list.
- wizweight
- Augment object descriptions with their objects' weight (default
- off). Debug mode only.
+ NetHack Guidebook 61
- zerocomp
- When writing out a save file, perform zero-comp compression of
- the contents. Not all ports support zero-comp compression. It
- has no effect on reading an existing save file.
- 9.5. Window Port Customization options
- Here are explanations of the various options that are used
- to customize and change the characteristics of the windowtype
- that you have chosen. Character strings that are too long may be
- truncated. Not all window ports will adjust for all settings
- listed here. You can safely add any of these options to your
- configuration file, and if the window port is capable of adjust-
- ing to suit your preferences, it will attempt to do so. If it
- can't it will silently ignore it. You can find out if an option
- is supported by the window port that you are currently using by
- checking to see if it shows up in the Options list. Some options
- are dynamic and can be specified during the game with the `O'
- command.
+ Persistent.
- align_message
- Where to align or place the message window (top, bottom, left,
- or right)
+ showscore
+ Show your approximate accumulated score on bottom line (default
+ off). Persistent.
+ silent
+ Suppress terminal beeps (default on). Persistent.
+ sortloot
+ Controls the sorting behavior of the pickup lists for inventory and
+ #loot commands and some others. Persistent. The possible values
+ are:
- NetHack 3.6 March 4, 2020
+ full - always sort the lists;
+ loot - only sort the lists that don't use inventory letters, like
+ with the #loot and pickup commands;
+ none - show lists the traditional way without sorting.
+ sortpack
+ Sort the pack contents by type when displaying inventory (default
+ on). Persistent.
+ sparkle
+ Display a sparkly effect when a monster (including yourself) is hit
+ by an attack to which it is resistant (default on). Persistent.
+ standout
+ Boldface monsters and "--More--" (default off). Persistent.
+ statushilites
+ Controls how many turns status hilite behaviors highlight the field.
+ If negated or set to zero, disables status hiliting. See "Configur-
+ ing Status Hilites" for further information.
- NetHack Guidebook 65
+ status_updates
+ Allow updates to the status lines at the bottom of the screen
+ (default true).
+ suppress_alert
+ This option may be set to a NetHack version level to suppress alert
+ notification messages about feature changes for that and prior ver-
+ sions (for example "suppress_alert:3.3.1").
+ symset
+ This option may be used to select one of the named symbol sets found
+ within "symbols" to alter the symbols displayed on the screen. Use
+ "symset:default" to explicitly select the default symbols.
- align_status
- Where to align or place the status window (top, bottom, left,
- or right).
+ time
+ Show the elapsed game time in turns on bottom line (default off).
+ Persistent.
- ascii_map
- If NetHack can, it should display an ascii character map if it
- can.
- color
- If NetHack can, it should display color if it can for different
- monsters, objects, and dungeon features.
- eight_bit_tty
- If NetHack can, it should pass eight-bit character values (for
- example, specified with the traps option) straight through to
- your terminal (default off).
- font_map
- if NetHack can, it should use a font by the chosen name for the
- map window.
+ NetHack 3.6.7 February 3, 2023
- font_menu
- If NetHack can, it should use a font by the chosen name for
- menu windows.
- font_message
- If NetHack can, it should use a font by the chosen name for the
- message window.
- font_status
- If NetHack can, it should use a font by the chosen name for the
- status window.
- font_text
- If NetHack can, it should use a font by the chosen name for
- text windows.
- font_size_map
- If NetHack can, it should use this size font for the map win-
- dow.
+ NetHack Guidebook 62
- font_size_menu
- If NetHack can, it should use this size font for menu windows.
- font_size_message
- If NetHack can, it should use this size font for the message
- window.
- font_size_status
- If NetHack can, it should use this size font for the status
- window.
+ timed_delay
+ When pausing momentarily for display effect, such as with explosions
+ and moving objects, use a timer rather than sending extra characters
+ to the screen. (Applies to "tty" interface only; "X11" interface
+ always uses a timer based delay. The default is on if configured
+ into the program.) Persistent.
- font_size_text
- If NetHack can, it should use this size font for text windows.
+ tombstone
+ Draw a tombstone graphic upon your death (default on). Persistent.
+ toptenwin
+ Put the ending display in a NetHack window instead of on stdout
+ (default off). Setting this option makes the score list visible
+ when a windowing version of NetHack is started without a parent win-
+ dow, but it no longer leaves the score list around after game end on
+ a terminal or emulating window.
- NetHack 3.6 March 4, 2020
+ travel
+ Allow the travel command (default on). Turning this option off will
+ prevent the game from attempting unintended moves if you make inad-
+ vertent mouse clicks on the map window. Persistent.
+ verbose
+ Provide more commentary during the game (default on). Persistent.
+ whatis_coord
+ When using the `/' or `;' commands to look around on the map with
+ autodescribe on, display coordinates after the description. Also
+ works in other situations where you are asked to pick a location.
+ The possible settings are:
+ c - compass ("east" or "3s" or "2n,4w");
+ f - full compass ("east" or "3south" or "2north,4west");
+ m - map (map column x=0 is not used);
+ s - screen [row,column] (row is offset to match tty usage);
+ n - none (no coordinates shown) [default].
- NetHack Guidebook 66
+ The whatis_coord option is also used with the "/m", "/M", "/o", and
+ "/O" sub-commands of `/', where the "none" setting is overridden
+ with "map".
+ whatis_filter
+ When getting a location on the map, and using the keys to cycle
+ through next and previous targets, allows filtering the possible
+ targets.
+ n - no filtering [default]
+ v - in view only
+ a - in same area only
- fullscreen
- If NetHack can, it should try and display on the entire screen
- rather than in a window.
+ The area-filter tries to be slightly predictive -- if you're stand-
+ ing on a doorway, it will consider the area on the side of the door
+ you were last moving towards.
- guicolor
- Use color text and/or highlighting attributes when displaying
- some non-map data (such as menu selector letters). Curses in-
- terface only; default is on.
- large_font
- If NetHack can, it should use a large font.
+ NetHack 3.6.7 February 3, 2023
- map_mode
- If NetHack can, it should display the map in the manner speci-
- fied.
- player_selection
- If NetHack can, it should pop up dialog boxes, or use prompts
- for character selection.
- popup_dialog
- If NetHack can, it should pop up dialog boxes for input.
- preload_tiles
- If NetHack can, it should preload tiles into memory. For exam-
- ple, in the protected mode MS-DOS version, control whether
- tiles get pre-loaded into RAM at the start of the game. Doing
- so enhances performance of the tile graphics, but uses more
- memory. (default on). Cannot be set with the `O' command.
- scroll_amount
- If NetHack can, it should scroll the display by this number of
- cells when the hero reaches the scroll_margin.
+ NetHack Guidebook 63
- scroll_margin
- If NetHack can, it should scroll the display when the hero or
- cursor is this number of cells away from the edge of the win-
- dow.
- selectsaved
- If NetHack can, it should display a menu of existing saved
- games for the player to choose from at game startup, if it can.
- Not all ports support this option.
- softkeyboard
- Display an onscreen keyboard. Handhelds are most likely to
- support this option.
+ Filtering can also be changed when getting a location with the "get-
+ pos.filter" key.
- splash_screen
- If NetHack can, it should display an opening splash screen when
- it starts up (default yes).
+ whatis_menu
+ When getting a location on the map, and using a key to cycle through
+ next and previous targets, use a menu instead to pick a target.
+ (default off)
- statuslines
- Number of lines for traditional below-the-map status display.
+ whatis_moveskip
+ When getting a location on the map, and using shifted movement keys
+ or meta-digit keys to fast-move, instead of moving 8 units at a
+ time, move by skipping the same glyphs. (default off)
+ windowtype
+ When the program has been built to support multiple interfaces,
+ select which one to use, such as "tty" or "X11" (default depends on
+ build-time settings; use "#version" to check). Cannot be set with
+ the `O' command.
- NetHack 3.6 March 4, 2020
+ When used, it should be the first option set since its value might
+ enable or disable the availability of various other options. For
+ multiple lines in a configuration file, that would be the first non-
+ comment line. For a comma-separated list in NETHACKOPTIONS or an
+ OPTIONS line in a configuration file, that would be the rightmost
+ option in the list.
+ wizweight
+ Augment object descriptions with their objects' weight (default
+ off). Debug mode only.
+ zerocomp
+ When writing out a save file, perform zero-comp compression of the
+ contents. Not all ports support zero-comp compression. It has no
+ effect on reading an existing save file.
+ 9.5. Window Port Customization options
+ Here are explanations of the various options that are used to
+ customize and change the characteristics of the windowtype that you
+ have chosen. Character strings that are too long may be truncated.
+ Not all window ports will adjust for all settings listed here. You
+ can safely add any of these options to your configuration file, and if
+ the window port is capable of adjusting to suit your preferences, it
+ will attempt to do so. If it can't it will silently ignore it. You
+ can find out if an option is supported by the window port that you are
+ currently using by checking to see if it shows up in the Options list.
+ Some options are dynamic and can be specified during the game with the
+ `O' command.
- NetHack Guidebook 67
+ align_message
+ Where to align or place the message window (top, bottom, left, or
+ right)
- Acceptable values are 2 and 3 (default is 2). Curses and tty
- interfaces only.
- term_cols and
+ NetHack 3.6.7 February 3, 2023
- term_rows
- Curses interface only. Number of columns and rows to use for
- the display. Curses will attempt to resize to the values spec-
- ified but will settle for smaller sizes if they are too big.
- Default is the current window size.
- tiled_map
- If NetHack can, it should display a tiled map if it can.
- tile_file
- Specify the name of an alternative tile file to override the
- default.
- tile_height
- Specify the preferred height of each tile in a tile capable
- port.
- tile_width
- Specify the preferred width of each tile in a tile capable port
+ NetHack Guidebook 64
- use_darkgray
- Use bold black instead of blue for black glyphs (TTY only).
- use_inverse
- If NetHack can, it should display inverse when the game speci-
- fies it.
- vary_msgcount
- If NetHack can, it should display this number of messages at a
- time in the message window.
+ align_status
+ Where to align or place the status window (top, bottom, left, or
+ right).
- windowborders
- Whether to draw boxes around the map, status area, message
- area, and persistent inventory window if enabled. Curses in-
- terface only. Acceptable values are
+ ascii_map
+ If NetHack can, it should display an ascii character map if it can.
- 0 - off, never show borders
- 1 - on, always show borders
- 2 - auto, on if display is at least (24+2)x(80+2) (default)
+ color
+ If NetHack can, it should display color if it can for different mon-
+ sters, objects, and dungeon features.
- (The 26x82 size threshold for `2' refers to number of rows and
- columns of the display. A width of at least 110 columns
- (80+2+26+2) is needed for align_status set to left or right.)
+ eight_bit_tty
+ If NetHack can, it should pass eight-bit character values (for exam-
+ ple, specified with the traps option) straight through to your ter-
+ minal (default off).
- windowcolors
- If NetHack can, it should display windows with the specified
- foreground/background colors. Windows GUI only. The format is
+ font_map
+ if NetHack can, it should use a font by the chosen name for the map
+ window.
+ font_menu
+ If NetHack can, it should use a font by the chosen name for menu
+ windows.
+ font_message
+ If NetHack can, it should use a font by the chosen name for the mes-
+ sage window.
+ font_status
+ If NetHack can, it should use a font by the chosen name for the sta-
+ tus window.
- NetHack 3.6 March 4, 2020
+ font_text
+ If NetHack can, it should use a font by the chosen name for text
+ windows.
+ font_size_map
+ If NetHack can, it should use this size font for the map window.
+ font_size_menu
+ If NetHack can, it should use this size font for menu windows.
+ font_size_message
+ If NetHack can, it should use this size font for the message window.
+ font_size_status
+ If NetHack can, it should use this size font for the status window.
- NetHack Guidebook 68
+ font_size_text
+ If NetHack can, it should use this size font for text windows.
+ fullscreen
+ If NetHack can, it should try and display on the entire screen
+ rather than in a window.
- OPTION=windowcolors:wintype foreground/background
+ NetHack 3.6.7 February 3, 2023
- where wintype is one of "menu", "message", "status", or
- "text", and foreground and background are colors, either a hexa-
- decimal \'#rrggbb', one of the named colors (black, red, green,
- brown, blue, magenta, cyan, orange, brightgreen, yellow, bright-
- blue, brightmagenta, brightcyan, white, trueblack, gray, purple,
- silver, maroon, fuchsia, lime, olive, navy, teal, aqua), or one
- of Windows UI colors (activeborder, activecaption, appworkspace,
- background, btnface, btnshadow, btntext, captiontext, graytext,
- greytext, highlight, highlighttext, inactiveborder, inactivecap-
- tion, menu, menutext, scrollbar, window, windowframe, window-
- text).
- wraptext
- If NetHack can, it should wrap long lines of text if they don't
- fit in the visible area of the window.
- 9.6. Platform-specific Customization options
- Here are explanations of options that are used by specific
- platforms or ports to customize and change the port behavior.
- altkeyhandler
- Select an alternate keystroke handler dll to load (Win32 tty
- NetHack only). The name of the handler is specified without
- the .dll extension and without any path information. Cannot be
- set with the `O' command.
+ NetHack Guidebook 65
- altmeta
- On Amiga, this option controls whether typing "Alt" plus anoth-
- er key functions as a meta-shift for that key (default on).
- altmeta
- On other (non-Amiga) systems where this option is available, it
- can be set to tell NetHack to convert a two character sequence
- beginning with ESC into a meta-shifted version of the second
- character (default off).
- This conversion is only done for commands, not for other input
- prompts. Note that typing one or more digits as a count prefix
- prior to a command -- preceded by n if the number_pad option is
- set -- is also subject to this conversion, so attempting to
- abort the count by typing ESC will leave NetHack waiting for
- another character to complete the two character sequence. Type
- a second ESC to finish cancelling such a count. At other
- prompts a single ESC suffices.
+ guicolor
+ Use color text and/or highlighting attributes when displaying some
+ non-map data (such as menu selector letters). Curses interface
+ only; default is on.
- BIOS
- Use BIOS calls to update the screen display quickly and to read
- the keyboard (allowing the use of arrow keys to move) on ma-
- chines with an IBM PC compatible BIOS ROM (default off, OS/2,
- PC, and ST NetHack only).
+ large_font
+ If NetHack can, it should use a large font.
+ map_mode
+ If NetHack can, it should display the map in the manner specified.
+ player_selection
+ If NetHack can, it should pop up dialog boxes, or use prompts for
+ character selection.
- NetHack 3.6 March 4, 2020
+ popup_dialog
+ If NetHack can, it should pop up dialog boxes for input.
+ preload_tiles
+ If NetHack can, it should preload tiles into memory. For example,
+ in the protected mode MS-DOS version, control whether tiles get pre-
+ loaded into RAM at the start of the game. Doing so enhances perfor-
+ mance of the tile graphics, but uses more memory. (default on).
+ Cannot be set with the `O' command.
+ scroll_amount
+ If NetHack can, it should scroll the display by this number of cells
+ when the hero reaches the scroll_margin.
+ scroll_margin
+ If NetHack can, it should scroll the display when the hero or cursor
+ is this number of cells away from the edge of the window.
+ selectsaved
+ If NetHack can, it should display a menu of existing saved games for
+ the player to choose from at game startup, if it can. Not all ports
+ support this option.
- NetHack Guidebook 69
+ softkeyboard
+ Display an onscreen keyboard. Handhelds are most likely to support
+ this option.
+ splash_screen
+ If NetHack can, it should display an opening splash screen when it
+ starts up (default yes).
+ statuslines
+ Number of lines for traditional below-the-map status display.
+ Acceptable values are 2 and 3 (default is 2). Curses and tty inter-
+ faces only.
- flush
- (default off, Amiga NetHack only).
+ term_cols and
- MACgraphics
- (default on, Mac NetHack only).
- page_wait
- (default on, Mac NetHack only).
- rawio
- Force raw (non-cbreak) mode for faster output and more bullet-
- proof input (MS-DOS sometimes treats `^P' as a printer toggle
- without it) (default off, OS/2, PC, and ST NetHack only).
- Note: DEC Rainbows hang if this is turned on. Cannot be set
- with the `O' command.
- soundcard
- (default on, PC NetHack only). Cannot be set with the `O' com-
- mand.
+ NetHack 3.6.7 February 3, 2023
- subkeyvalue
- (Win32 tty NetHack only). May be used to alter the value of
- keystrokes that the operating system returns to NetHack to help
- compensate for international keyboard issues. OPTIONS=subkey-
- value:171/92 will return 92 to NetHack, if 171 was originally
- going to be returned. You can use multiple subkeyvalue state-
- ments in the configuration file if needed. Cannot be set with
- the `O' command.
- video
- Set the video mode used (PC NetHack only). Values are "autode-
- tect", "default", or "vga". Setting "vga" (or "autodetect"
- with vga hardware present) will cause the game to display
- tiles. Cannot be set with the `O' command.
- videocolors
- Set the color palette for PC systems using NO_TERMS (default
- 4-2-6-1-5-3-15-12-10-14-9-13-11, (PC NetHack only). The order
- of colors is red, green, brown, blue, magenta, cyan,
- bright.white, bright.red, bright.green, yellow, bright.blue,
- bright.magenta, and bright.cyan. Cannot be set with the `O'
- command.
- videoshades
- Set the intensity level of the three gray scales available (de-
- fault dark normal light, PC NetHack only). If the game display
- is difficult to read, try adjusting these scales; if this does
- not correct the problem, try !color. Cannot be set with the
- `O' command.
- 9.7. Regular Expressions
+ NetHack Guidebook 66
- Regular expressions are normally POSIX extended regular ex-
- pressions. It is possible to compile NetHack without regular
- NetHack 3.6 March 4, 2020
+ term_rows
+ Curses interface only. Number of columns and rows to use for the
+ display. Curses will attempt to resize to the values specified but
+ will settle for smaller sizes if they are too big. Default is the
+ current window size.
+ tiled_map
+ If NetHack can, it should display a tiled map if it can.
+ tile_file
+ Specify the name of an alternative tile file to override the
+ default.
+ tile_height
+ Specify the preferred height of each tile in a tile capable port.
+ tile_width
+ Specify the preferred width of each tile in a tile capable port
- NetHack Guidebook 70
+ use_darkgray
+ Use bold black instead of blue for black glyphs (TTY only).
+ use_inverse
+ If NetHack can, it should display inverse when the game specifies
+ it.
+ vary_msgcount
+ If NetHack can, it should display this number of messages at a time
+ in the message window.
- expression support on a platform where there is no regular ex-
- pression library. While this is not true of any modern platform,
- if your NetHack was built this way, patterns are instead glob
- patterns. This applies to Autopickup exceptions, Message types,
- Menu colors, and User sounds.
+ windowborders
+ Whether to draw boxes around the map, status area, message area, and
+ persistent inventory window if enabled. Curses interface only.
+ Acceptable values are
- 9.8. Configuring Autopickup Exceptions
+ 0 - off, never show borders
+ 1 - on, always show borders
+ 2 - auto, on if display is at least (24+2)x(80+2) (default)
- You can further refine the behavior of the autopickup option
- beyond what is available through the pickup_types option.
+ (The 26x82 size threshold for `2' refers to number of rows and col-
+ umns of the display. A width of at least 110 columns (80+2+26+2) is
+ needed for align_status set to left or right.)
- By placing autopickup_exception lines in your configuration
- file, you can define patterns to be checked when the game is
- about to autopickup something.
+ windowcolors
+ If NetHack can, it should display windows with the specified fore-
+ ground/background colors. Windows GUI only. The format is
- autopickup_exception
- Sets an exception to the pickup_types option. The autopick-
- up_exception option should be followed by a regular expression
- to be used as a pattern to match against the singular form of
- the description of an object at your location.
+ OPTION=windowcolors:wintype foreground/background
- In addition, some characters are treated specially if they oc-
- cur as the first character in the pattern, specifically:
+ where wintype is one of "menu", "message", "status", or "text",
+ and foreground and background are colors, either a hexadecimal
+ \'#rrggbb', one of the named colors (black, red, green, brown, blue,
+ magenta, cyan, orange, brightgreen, yellow, brightblue, brightmagenta,
+ brightcyan, white, trueblack, gray, purple, silver, maroon, fuchsia,
- < - always pickup an object that matches rest of pattern;
- > - never pickup an object that matches rest of pattern.
- The autopickup_exception rules are processed in the order in
- which they appear in your configuration file, thus allowing a
- later rule to override an earlier rule.
+ NetHack 3.6.7 February 3, 2023
- Exceptions can be set with the `O' command, but because they
- are not included in your configuration file, they won't be in
- effect if you save and then restore your game. autopickup_ex-
- ception rules and not saved with the game.
- Here are some examples:
- autopickup_exception="<*arrow"
- autopickup_exception=">*corpse"
- autopickup_exception=">* cursed*"
- The first example above will result in autopickup of any
- type of arrow. The second example results in the exclusion of
- any corpse from autopickup. The last example results in the ex-
- clusion of items known to be cursed from autopickup.
- 9.9. Changing Key Bindings
+ NetHack Guidebook 67
- It is possible to change the default key bindings of some
- special commands, menu accelerator keys, and extended commands,
- by using BIND stanzas in the configuration file. Format is key,
- followed by the command to bind to, separated by a colon. The
- key can be a single character ("x"), a control key ("^X", "C-x"),
- NetHack 3.6 March 4, 2020
+ lime, olive, navy, teal, aqua), or one of Windows UI colors (active-
+ border, activecaption, appworkspace, background, btnface, btnshadow,
+ btntext, captiontext, graytext, greytext, highlight, highlighttext,
+ inactiveborder, inactivecaption, menu, menutext, scrollbar, window,
+ windowframe, windowtext).
+ wraptext
+ If NetHack can, it should wrap long lines of text if they don't fit
+ in the visible area of the window.
+ 9.6. Platform-specific Customization options
+ Here are explanations of options that are used by specific plat-
+ forms or ports to customize and change the port behavior.
+ altkeyhandling
+ Select an alternate way to handle keystrokes (Win32 tty NetHack
+ only). The name of the handling type is one of "default", "ray",
+ "340".
- NetHack Guidebook 71
+ altmeta
+ On Amiga, this option controls whether typing "Alt" plus another key
+ functions as a meta-shift for that key (default on).
+ altmeta
+ On other (non-Amiga) systems where this option is available, it can
+ be set to tell NetHack to convert a two character sequence beginning
+ with ESC into a meta-shifted version of the second character
+ (default off).
+ This conversion is only done for commands, not for other input
+ prompts. Note that typing one or more digits as a count prefix
+ prior to a command -- preceded by n if the number_pad option is set
+ -- is also subject to this conversion, so attempting to abort the
+ count by typing ESC will leave NetHack waiting for another character
+ to complete the two character sequence. Type a second ESC to finish
+ cancelling such a count. At other prompts a single ESC suffices.
- a meta key ("M-x"), or a three-digit decimal ASCII code.
+ BIOS
+ Use BIOS calls to update the screen display quickly and to read the
+ keyboard (allowing the use of arrow keys to move) on machines with
+ an IBM PC compatible BIOS ROM (default off, OS/2, PC, and ST NetHack
+ only).
- For example:
+ flush
+ (default off, Amiga NetHack only).
- BIND=^X:getpos.autodescribe
- BIND={:menu_first_page
- BIND=v:loot
+ MACgraphics
+ (default on, Mac NetHack only).
- Extended command keys
- You can bind multiple keys to the same extended command. Un-
- bind a key by using "nothing" as the extended command to bind
- to. You can also bind the "", "", and ""
- keys.
+ page_wait
+ (default on, Mac NetHack only).
- Menu accelerator keys
- The menu control or accelerator keys can also be rebound via
- OPTIONS lines in the configuration file. You cannot bind ob-
- ject symbols into menu accelerators.
- Special command keys
- Below are the special commands you can rebind. Some of them
- can be bound to same keys with no problems, others are in the
- same "context", and if bound to same keys, only one of those
- commands will be available. Special command can only be bound
- to a single key.
- count
- Prefix key to start a count, to repeat a command this many
- times. With number_pad only. Default is `n'.
- doinv
- Show inventory. With number_pad only. Default is `0'.
+ NetHack 3.6.7 February 3, 2023
- fight
- Prefix key to force fight a direction. Default is `F'.
- fight.numpad
- Prefix key to force fight a direction. With number_pad only.
- Default is `-'.
- getdir.help
- When asked for a direction, the key to show the help. Default
- is `?'.
- getdir.self
- When asked for a direction, the key to target yourself. De-
- fault is `.'.
- getdir.self2
- When asked for a direction, the key to target yourself. De-
- fault is `s'.
+ NetHack Guidebook 68
- getpos.autodescribe
- When asked for a location, the key to toggle autodescribe.
- NetHack 3.6 March 4, 2020
+ rawio
+ Force raw (non-cbreak) mode for faster output and more bulletproof
+ input (MS-DOS sometimes treats `^P' as a printer toggle without it)
+ (default off, OS/2, PC, and ST NetHack only). Note: DEC Rainbows
+ hang if this is turned on. Cannot be set with the `O' command.
+ soundcard
+ (default on, PC NetHack only). Cannot be set with the `O' command.
+ subkeyvalue
+ (Win32 tty NetHack only). May be used to alter the value of key-
+ strokes that the operating system returns to NetHack to help compen-
+ sate for international keyboard issues. OPTIONS=subkeyvalue:171/92
+ will return 92 to NetHack, if 171 was originally going to be
+ returned. You can use multiple subkeyvalue statements in the con-
+ figuration file if needed. Cannot be set with the `O' command.
+ video
+ Set the video mode used (PC NetHack only). Values are "autodetect",
+ "default", or "vga". Setting "vga" (or "autodetect" with vga hard-
+ ware present) will cause the game to display tiles. Cannot be set
+ with the `O' command.
+ videocolors
+ Set the color palette for PC systems using NO_TERMS (default
+ 4-2-6-1-5-3-15-12-10-14-9-13-11, (PC NetHack only). The order of
+ colors is red, green, brown, blue, magenta, cyan, bright.white,
+ bright.red, bright.green, yellow, bright.blue, bright.magenta, and
+ bright.cyan. Cannot be set with the `O' command.
- NetHack Guidebook 72
+ videoshades
+ Set the intensity level of the three gray scales available (default
+ dark normal light, PC NetHack only). If the game display is diffi-
+ cult to read, try adjusting these scales; if this does not correct
+ the problem, try !color. Cannot be set with the `O' command.
+ 9.7. Regular Expressions
+ Regular expressions are normally POSIX extended regular expres-
+ sions. It is possible to compile NetHack without regular expression
+ support on a platform where there is no regular expression library.
+ While this is not true of any modern platform, if your NetHack was
+ built this way, patterns are instead glob patterns. This applies to
+ Autopickup exceptions, Message types, Menu colors, and User sounds.
- Default is `#'.
+ 9.8. Configuring Autopickup Exceptions
- getpos.all.next
- When asked for a location, the key to go to next closest inter-
- esting thing. Default is `a'.
+ You can further refine the behavior of the autopickup option
+ beyond what is available through the pickup_types option.
- getpos.all.prev
- When asked for a location, the key to go to previous closest
- interesting thing. Default is `A'.
+ By placing autopickup_exception lines in your configuration file,
+ you can define patterns to be checked when the game is about to
+ autopickup something.
- getpos.door.next
- When asked for a location, the key to go to next closest door
- or doorway. Default is `d'.
- getpos.door.prev
- When asked for a location, the key to go to previous closest
- door or doorway. Default is `D'.
- getpos.help
- When asked for a location, the key to show help. Default is
- `?'.
+ NetHack 3.6.7 February 3, 2023
- getpos.mon.next
- When asked for a location, the key to go to next closest mon-
- ster. Default is `m'.
- getpos.mon.prev
- When asked for a location, the key to go to previous closest
- monster. Default is `M'.
- getpos.obj.next
- When asked for a location, the key to go to next closest ob-
- ject. Default is `o'.
- getpos.obj.prev
- When asked for a location, the key to go to previous closest
- object. Default is `O'.
- getpos.menu
- When asked for a location, and using one of the next or previ-
- ous keys to cycle through targets, toggle showing a menu in-
- stead. Default is `!'.
+ NetHack Guidebook 69
- getpos.moveskip
- When asked for a location, and using the shifted movement keys
- or meta-digit keys to fast-move around, move by skipping the
- same glyphs instead of by 8 units. Default is `*'.
- getpos.filter
- When asked for a location, change the filtering mode when using
- one of the next or previous keys to cycle through targets.
- Toggles between no filtering, in view only, and in the same
- area only. Default is `"'.
+ autopickup_exception
+ Sets an exception to the pickup_types option. The autopickup_excep-
+ tion option should be followed by a regular expression to be used as
+ a pattern to match against the singular form of the description of
+ an object at your location.
+ In addition, some characters are treated specially if they occur as
+ the first character in the pattern, specifically:
- NetHack 3.6 March 4, 2020
+ < - always pickup an object that matches rest of pattern;
+ > - never pickup an object that matches rest of pattern.
+ The autopickup_exception rules are processed in the order in which
+ they appear in your configuration file, thus allowing a later rule
+ to override an earlier rule.
+ Exceptions can be set with the `O' command, but because they are not
+ included in your configuration file, they won't be in effect if you
+ save and then restore your game. autopickup_exception rules and not
+ saved with the game.
+ Here are some examples:
+ autopickup_exception="<*arrow"
+ autopickup_exception=">*corpse"
+ autopickup_exception=">* cursed*"
- NetHack Guidebook 73
+ The first example above will result in autopickup of any type of
+ arrow. The second example results in the exclusion of any corpse from
+ autopickup. The last example results in the exclusion of items known
+ to be cursed from autopickup.
+ 9.9. Changing Key Bindings
+ It is possible to change the default key bindings of some special
+ commands, menu accelerator keys, and extended commands, by using BIND
+ stanzas in the configuration file. Format is key, followed by the
+ command to bind to, separated by a colon. The key can be a single
+ character ("x"), a control key ("^X", "C-x"), a meta key ("M-x"), or a
+ three-digit decimal ASCII code.
- getpos.pick
- When asked for a location, the key to choose the location, and
- possibly ask for more info. Default is `.'.
+ For example:
- getpos.pick.once
- When asked for a location, the key to choose the location, and
- skip asking for more info. Default is `,'.
+ BIND=^X:getpos.autodescribe
+ BIND={:menu_first_page
+ BIND=v:loot
- getpos.pick.quick
- When asked for a location, the key to choose the location, skip
- asking for more info, and exit the location asking loop. De-
- fault is `;'.
+ Extended command keys
+ You can bind multiple keys to the same extended command. Unbind a
+ key by using "nothing" as the extended command to bind to. You can
+ also bind the "", "", and "" keys.
- getpos.pick.verbose
- When asked for a location, the key to choose the location, and
- show more info without asking. Default is `:'.
+ Menu accelerator keys
+ The menu control or accelerator keys can also be rebound via OPTIONS
- getpos.self
- When asked for a location, the key to go to your location. De-
- fault is `@'.
- getpos.unexplored.next
- When asked for a location, the key to go to next closest unex-
- plored location. Default is `x'.
+ NetHack 3.6.7 February 3, 2023
- getpos.unexplored.prev
- When asked for a location, the key to go to previous closest
- unexplored location. Default is `X'.
- getpos.valid
- When asked for a location, the key to go to show valid target
- locations. Default is `$'.
- getpos.valid.next
- When asked for a location, the key to go to next closest valid
- location. Default is `z'.
- getpos.valid.prev
- When asked for a location, the key to go to previous closest
- valid location. Default is `Z'.
- nopickup
- Prefix key to move without picking up items. Default is `m'.
+ NetHack Guidebook 70
- redraw
- Key to redraw the screen. Default is `^R'.
- redraw.numpad
- Key to redraw the screen. With number_pad only. Default is
- `^L'.
- repeat
- Key to repeat previous command. Default is `^A'.
+ lines in the configuration file. You cannot bind object symbols
+ into menu accelerators.
+ Special command keys
+ Below are the special commands you can rebind. Some of them can be
+ bound to same keys with no problems, others are in the same "con-
+ text", and if bound to same keys, only one of those commands will be
+ available. Special command can only be bound to a single key.
+ count
+ Prefix key to start a count, to repeat a command this many times.
+ With number_pad only. Default is `n'.
- NetHack 3.6 March 4, 2020
+ doinv
+ Show inventory. With number_pad only. Default is `0'.
+ fight
+ Prefix key to force fight a direction. Default is `F'.
+ fight.numpad
+ Prefix key to force fight a direction. With number_pad only.
+ Default is `-'.
+ getdir.help
+ When asked for a direction, the key to show the help. Default is
+ `?'.
+ getdir.self
+ When asked for a direction, the key to target yourself. Default is
+ `.'.
- NetHack Guidebook 74
+ getdir.self2
+ When asked for a direction, the key to target yourself. Default is
+ `s'.
+ getpos.autodescribe
+ When asked for a location, the key to toggle autodescribe. Default
+ is `#'.
+ getpos.all.next
+ When asked for a location, the key to go to next closest interesting
+ thing. Default is `a'.
- reqmenu
- Prefix key to request menu from some commands. Default is `m'.
+ getpos.all.prev
+ When asked for a location, the key to go to previous closest inter-
+ esting thing. Default is `A'.
- run
- Prefix key to run towards a direction. Default is `G'.
+ getpos.door.next
+ When asked for a location, the key to go to next closest door or
+ doorway. Default is `d'.
- run.nopickup
- Prefix key to run towards a direction without picking up items
- on the way. Default is `M'.
+ getpos.door.prev
+ When asked for a location, the key to go to previous closest door or
+ doorway. Default is `D'.
- run.numpad
- Prefix key to run towards a direction. With number_pad only.
- Default is `5'.
- rush
- Prefix key to rush towards a direction. Default is `g'.
+ NetHack 3.6.7 February 3, 2023
- 9.10. Configuring Message Types
- You can change the way the messages are shown in the message
- area, when the message matches a user-defined pattern.
- In general, the configuration file entries to describe the
- message types look like this: MSGTYPE=type "pattern"
- type - how the message should be shown;
- pattern - the pattern to match.
- The pattern should be a regular expression.
+ NetHack Guidebook 71
- Allowed types are:
- show - show message normally;
- hide - never show the message;
- stop - wait for user with more-prompt;
- norep - show the message once, but not again if no other mes-
- sage is shown in between.
- Here's an example of message types using NetHack's internal
- pattern matching facility:
+ getpos.help
+ When asked for a location, the key to show help. Default is `?'.
- MSGTYPE=stop "You feel hungry."
- MSGTYPE=hide "You displaced *."
+ getpos.mon.next
+ When asked for a location, the key to go to next closest monster.
+ Default is `m'.
- specifies that whenever a message "You feel hungry" is shown,
- the user is prompted with more-prompt, and a message matching
- "You displaced ." is not shown at all.
+ getpos.mon.prev
+ When asked for a location, the key to go to previous closest mon-
+ ster. Default is `M'.
- The order of the defined MSGTYPE lines is important; the last
- matching rule is used. Put the general case first, exceptions
- below them.
+ getpos.obj.next
+ When asked for a location, the key to go to next closest object.
+ Default is `o'.
+ getpos.obj.prev
+ When asked for a location, the key to go to previous closest object.
+ Default is `O'.
+ getpos.menu
+ When asked for a location, and using one of the next or previous
+ keys to cycle through targets, toggle showing a menu instead.
+ Default is `!'.
+ getpos.moveskip
+ When asked for a location, and using the shifted movement keys or
+ meta-digit keys to fast-move around, move by skipping the same
+ glyphs instead of by 8 units. Default is `*'.
+ getpos.filter
+ When asked for a location, change the filtering mode when using one
+ of the next or previous keys to cycle through targets. Toggles
+ between no filtering, in view only, and in the same area only.
+ Default is `"'.
- NetHack 3.6 March 4, 2020
+ getpos.pick
+ When asked for a location, the key to choose the location, and pos-
+ sibly ask for more info. Default is `.'.
+ getpos.pick.once
+ When asked for a location, the key to choose the location, and skip
+ asking for more info. Default is `,'.
+ getpos.pick.quick
+ When asked for a location, the key to choose the location, skip ask-
+ ing for more info, and exit the location asking loop. Default is
+ `;'.
+ getpos.pick.verbose
+ When asked for a location, the key to choose the location, and show
+ more info without asking. Default is `:'.
+ getpos.self
+ When asked for a location, the key to go to your location. Default
- NetHack Guidebook 75
+ NetHack 3.6.7 February 3, 2023
- 9.11. Configuring Menu Colors
- Some platforms allow you to define colors used in menu lines
- when the line matches a user-defined pattern. At this time the
- tty, curses, win32tty and win32gui interfaces support this.
- In general, the configuration file entries to describe the
- menu color mappings look like this:
- MENUCOLOR="pattern"=color&attribute
+ NetHack Guidebook 72
- pattern - the pattern to match;
- color - the color to use for lines matching the pat-
- tern;
- attribute - the attribute to use for lines matching the
- pattern. The attribute is optional, and if
- left out, you must also leave out the preced-
- ing ampersand. If no attribute is defined,
- no attribute is used.
- The pattern should be a regular expression.
- Allowed colors are black, red, green, brown, blue, magenta,
- cyan, gray, orange, light-green, yellow, light-blue, light-ma-
- genta, light-cyan, and white. And no-color, the default fore-
- ground color, which isn't necessarily the same as any of the
- other colors.
+ is `@'.
- Allowed attributes are none, bold, dim, underline, blink, and
- inverse. "Normal" is a synonym for "none". Note that the
- platform used may interpret the attributes any way it wants.
+ getpos.unexplored.next
+ When asked for a location, the key to go to next closest unexplored
+ location. Default is `x'.
- Here's an example of menu colors using NetHack's internal pat-
- tern matching facility:
+ getpos.unexplored.prev
+ When asked for a location, the key to go to previous closest unex-
+ plored location. Default is `X'.
- MENUCOLOR="* blessed *"=green
- MENUCOLOR="* cursed *"=red
- MENUCOLOR="* cursed *(being worn)"=red&underline
+ getpos.valid
+ When asked for a location, the key to go to show valid target loca-
+ tions. Default is `$'.
- specifies that any menu line with " blessed " contained in it
- will be shown in green color, lines with " cursed " will be
- shown in red, and lines with " cursed " followed by "(being
- worn)" on the same line will be shown in red color and under-
- lined. You can have multiple MENUCOLOR entries in your config-
- uration file, and the last MENUCOLOR line that matches a menu
- line will be used for the line.
+ getpos.valid.next
+ When asked for a location, the key to go to next closest valid loca-
+ tion. Default is `z'.
- Note that if you intend to have one or more color specifica-
- tions match " uncursed ", you will probably want to turn the im-
- plicit_uncursed option off so that all items known to be uncursed
- are actually displayed with the "uncursed" description.
+ getpos.valid.prev
+ When asked for a location, the key to go to previous closest valid
+ location. Default is `Z'.
+ nopickup
+ Prefix key to move without picking up items. Default is `m'.
+ redraw
+ Key to redraw the screen. Default is `^R'.
+ redraw.numpad
+ Key to redraw the screen. With number_pad only. Default is `^L'.
+ repeat
+ Key to repeat previous command. Default is `^A'.
- NetHack 3.6 March 4, 2020
+ reqmenu
+ Prefix key to request menu from some commands. Default is `m'.
+ run
+ Prefix key to run towards a direction. Default is `G'.
+ run.nopickup
+ Prefix key to run towards a direction without picking up items on
+ the way. Default is `M'.
+ run.numpad
+ Prefix key to run towards a direction. With number_pad only.
+ Default is `5'.
+ rush
+ Prefix key to rush towards a direction. Default is `g'.
- NetHack Guidebook 76
- 9.12. Configuring User Sounds
- Some platforms allow you to define sound files to be played
- when a message that matches a user-defined pattern is delivered
- to the message window. At this time the Qt port and the win32tty
- and win32gui ports support the use of user sounds.
- The following configuration file entries are relevant to
- mapping user sounds to messages:
+ NetHack 3.6.7 February 3, 2023
- SOUNDDIR
- The directory that houses the sound files to be played.
- SOUND
- An entry that maps a sound file to a user-specified message
- pattern. Each SOUND entry is broken down into the following
- parts:
- MESG - message window mapping (the only one supported in
- 3.6);
+
+
+ NetHack Guidebook 73
+
+
+
+ 9.10. Configuring Message Types
+
+ You can change the way the messages are shown in the message
+ area, when the message matches a user-defined pattern.
+
+ In general, the configuration file entries to describe the mes-
+ sage types look like this: MSGTYPE=type "pattern"
+
+ type - how the message should be shown;
+ pattern - the pattern to match.
+
+ The pattern should be a regular expression.
+
+ Allowed types are:
+
+ show - show message normally;
+ hide - never show the message;
+ stop - wait for user with more-prompt;
+ norep - show the message once, but not again if no other message is
+ shown in between.
+
+ Here's an example of message types using NetHack's internal pattern
+ matching facility:
+
+ MSGTYPE=stop "You feel hungry."
+ MSGTYPE=hide "You displaced *."
+
+ specifies that whenever a message "You feel hungry" is shown, the
+ user is prompted with more-prompt, and a message matching "You dis-
+ placed ." is not shown at all.
+
+ The order of the defined MSGTYPE lines is important; the last match-
+ ing rule is used. Put the general case first, exceptions below them.
+
+ 9.11. Configuring Menu Colors
+
+ Some platforms allow you to define colors used in menu lines when
+ the line matches a user-defined pattern. At this time the tty,
+ curses, win32tty and win32gui interfaces support this.
+
+ In general, the configuration file entries to describe the menu
+ color mappings look like this:
+
+ MENUCOLOR="pattern"=color&attribute
+
pattern - the pattern to match;
- sound file - the sound file to play;
- volume - the volume to be set while playing the sound file.
+ color - the color to use for lines matching the pattern;
+ attribute - the attribute to use for lines matching the pat-
+ tern. The attribute is optional, and if left out,
+ you must also leave out the preceding ampersand.
+ If no attribute is defined, no attribute is used.
+
+ The pattern should be a regular expression.
+
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 74
+
+
+
+ Allowed colors are black, red, green, brown, blue, magenta, cyan,
+ gray, orange, light-green, yellow, light-blue, light-magenta, light-
+ cyan, and white. And no-color, the default foreground color, which
+ isn't necessarily the same as any of the other colors.
+
+ Allowed attributes are none, bold, dim, underline, blink, and
+ inverse. "Normal" is a synonym for "none". Note that the platform
+ used may interpret the attributes any way it wants.
+
+ Here's an example of menu colors using NetHack's internal pattern
+ matching facility:
+
+ MENUCOLOR="* blessed *"=green
+ MENUCOLOR="* cursed *"=red
+ MENUCOLOR="* cursed *(being worn)"=red&underline
+
+ specifies that any menu line with " blessed " contained in it will
+ be shown in green color, lines with " cursed " will be shown in red,
+ and lines with " cursed " followed by "(being worn)" on the same
+ line will be shown in red color and underlined. You can have multi-
+ ple MENUCOLOR entries in your configuration file, and the last MENU-
+ COLOR line that matches a menu line will be used for the line.
+
+ Note that if you intend to have one or more color specifications
+ match " uncursed ", you will probably want to turn the
+ implicit_uncursed option off so that all items known to be uncursed
+ are actually displayed with the "uncursed" description.
+
+ 9.12. Configuring User Sounds
+
+ Some platforms allow you to define sound files to be played when
+ a message that matches a user-defined pattern is delivered to the mes-
+ sage window. At this time the Qt port and the win32tty and win32gui
+ ports support the use of user sounds.
+
+ The following configuration file entries are relevant to mapping
+ user sounds to messages:
+
+ SOUNDDIR
+ The directory that houses the sound files to be played.
+
+ SOUND
+ An entry that maps a sound file to a user-specified message pattern.
+ Each SOUND entry is broken down into the following parts:
+
+ MESG - message window mapping (the only one supported in 3.6);
+ pattern - the pattern to match;
+ sound file - the sound file to play;
+ volume - the volume to be set while playing the sound file.
+
+ The pattern should be a POSIX extended regular expression.
+
+
+
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 75
+
+
+
+ 9.13. Configuring Status Hilites
+
+ Your copy of NetHack may have been compiled with support for
+ "Status Hilites". If so, you can customize your game display by set-
+ ting thresholds to change the color or appearance of fields in the
+ status display.
+
+ The format for defining status colors is:
+
+ OPTION=hilite_status:field-name/behavior/color&attributes
+
+ For example, the following line in your configuration file will
+ cause the hitpoints field to display in the color red if your hit-
+ points drop to or below a threshold of 30%:
+
+ OPTION=hilite_status:hitpoints/<=30%/red/normal
+
+ (That example is actually specifying red&normal for <=30% and no-
+ color&normal for >30%.)
+
+ For another example, the following line in your configuration
+ file will cause wisdom to be displayed red if it drops and green if it
+ rises:
+
+ OPTION=hilite_status:wisdom/down/red/up/green
+
+ Allowed colors are black, red, green, brown, blue, magenta, cyan,
+ gray, orange, light-green, yellow, light-blue, light-magenta, light-
+ cyan, and white. And "no-color", the default foreground color on the
+ display, which is not necessarily the same as black or white or any of
+ the other colors.
+
+ Allowed attributes are none, bold, dim, underline, blink, and
+ inverse. "Normal" is a synonym for "none"; they should not be used in
+ combination with any of the other attributes.
+
+ To specify both a color and an attribute, use `&' to combine
+ them. To specify multiple attributes, use `+' to combine those. For
+ example: "magenta&inverse+dim".
+
+ Note that the display may substitute or ignore particular
+ attributes depending upon its capabilities, and in general may inter-
+ pret the attributes any way it wants. For example, on some display
+ systems a request for bold might yield blink or vice versa. On oth-
+ ers, issuing an attribute request while another is already set up will
+ replace the earlier attribute rather than combine with it. Since
+ NetHack issues attribute requests sequentially (at least with the tty
+ interface) rather than all at once, the only way a situation like that
+ can be controlled is to specify just one attribute.
+
+ You can adjust the appearance of the following status fields:
+ title dungeon-level experience-level
+ strength gold experience
+
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 76
+
+
+
+ dexterity hitpoints HD
+ constitution hitpoints-max time
+ intelligence power hunger
+ wisdom power-max carrying-capacity
+ charisma armor-class condition
+ alignment score
+
+ The pseudo-field "characteristics" can be used to set all six of
+ Str, Dex, Con, Int, Wis, and Cha at once. "HD" is "hit dice", an
+ approximation of experience level displayed when polymorphed.
+ "experience", "time", and "score" are conditionally displayed
+ depending upon your other option settings.
+
+ Instead of a behavior, "condition" takes the following condition
+ flags: stone, slime, strngl, foodpois, termill, blind, deaf, stun,
+ conf, hallu, lev, fly, and ride. You can use "major_troubles" as an
+ alias for stone through termill, "minor_troubles" for blind through
+ hallu, "movement" for lev, fly, and ride, and "all" for every condi-
+ tion.
+
+ Allowed behaviors are "always", "up", "down", "changed", a percent-
+ age or absolute number threshold, or text to match against.
+
+ * "always" will set the default attributes for that field.
+
+ * "up", "down" set the field attributes for when the field value
+ changes upwards or downwards. This attribute times out after
+ statushilites turns.
+
+ * "changed" sets the field attribute for when the field value
+ changes. This attribute times out after statushilites turns.
+ (If a field has both a "changed" rule and an "up" or "down"
+ rule which matches a change in the field's value, the "up" or
+ "down" one takes precedence.)
+
+ * percentage sets the field attribute when the field value
+ matches the percentage. It is specified as a number between 0
+ and 100, followed by `%' (percent sign). If the percentage is
+ prefixed with `<=' or `>=', it also matches when value is below
+ or above the percentage. Use prefix `<' or `>' to match when
+ strictly below or above. (The numeric limit is relaxed
+ slightly for those: >-1% and <101% are allowed.) Only four
+ fields support percentage rules. Percentages for "hitpoints"
+ and "power" are straightforward; they're based on the corre-
+ sponding maximum field. Percentage highlight rules are also
+ allowed for "experience level" and "experience points" (valid
+ when the showexp option is enabled). For those, the percentage
+ is based on the progress from the start of the current experi-
+ ence level to the start of the next level. So if level 2
+ starts at 20 points and level 3 starts at 40 points, having 30
+ points is 50% and 35 points is 75%. 100% is unattainable for
+ experience because you'll gain a level and the calculations
+ will be reset for that new level, but a rule for =100% is
+ allowed and matches the special case of being exactly 1 experi-
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 77
+
+
+
+ ence point short of the next level.
+
+ * absolute value sets the attribute when the field value matches
+ that number. The number must be 0 or higher, except for
+ "armor-class' which allows negative values, and may optionally
+ be preceded by `='. If the number is preceded by `<=' or `>='
+ instead, it also matches when value is below or above. If the
+ prefix is `<' or `>', only match when strictly above or below.
+
+ * text match sets the attribute when the field value matches the
+ text. Text matches can only be used for "alignment", "carry-
+ ing-capacity", "hunger", "dungeon-level", and "title". For
+ title, only the role's rank title is tested; the character's
+ name is ignored.
+
+ The in-game options menu can help you determine the correct syn-
+ tax for a configuration file.
+
+ The whole feature can be disabled by setting option statushilites
+ to 0.
+
+ Example hilites:
+
+ OPTION=hilite_status: gold/up/yellow/down/brown
+ OPTION=hilite_status: characteristics/up/green/down/red
+ OPTION=hilite_status: hitpoints/100%/gray&normal
+ OPTION=hilite_status: hitpoints/<100%/green&normal
+ OPTION=hilite_status: hitpoints/<66%/yellow&normal
+ OPTION=hilite_status: hitpoints/<50%/orange&normal
+ OPTION=hilite_status: hitpoints/<33%/red&bold
+ OPTION=hilite_status: hitpoints/<15%/red&inverse
+ OPTION=hilite_status: condition/major/orange&inverse
+ OPTION=hilite_status: condition/lev+fly/red&inverse
+
+ 9.14. Modifying NetHack Symbols
+
+ NetHack can load entire symbol sets from the symbol file.
+
+ The options that are used to select a particular symbol set from
+ the symbol file are:
+
+ symset
+ Set the name of the symbol set that you want to load.
+
+ roguesymset
+ Set the name of the symbol set that you want to load for display on
+ the rogue level.
+
+ You can also override one or more symbols using the SYMBOLS and
+ ROGUESYMBOLS configuration file options. Symbols are specified as
+ name:value pairs. Note that NetHack escape-processes the value string
+ in conventional C fashion. This means that \ is a prefix to take the
+ following character literally. Thus \ needs to be represented as \\.
+ The special prefix form \m switches on the meta bit in the symbol
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 78
+
+
+
+ value, and the ^ prefix causes the following character to be treated
+ as a control character.
+
+ NetHack Symbols
+ Symbol Name Description
+ -----------------------------------------------------------------
+ S_air (air)
+ _ S_altar (altar)
+ " S_amulet (amulet)
+ A S_angel (angelic being)
+ a S_ant (ant or other insect)
+ ^ S_anti_magic_trap (anti-magic field)
+ [ S_armor (suit or piece of armor)
+ [ S_armour (suit or piece of armor)
+ ^ S_arrow_trap (arrow trap)
+ 0 S_ball (iron ball)
+ # S_bars (iron bars)
+ B S_bat (bat or bird)
+ ^ S_bear_trap (bear trap)
+ - S_blcorn (bottom left corner)
+ b S_blob (blob)
+ + S_book (spellbook)
+ ) S_boomleft (boomerang open left)
+ ( S_boomright (boomerang open right)
+ ` S_boulder (boulder)
+ - S_brcorn (bottom right corner)
+ C S_centaur (centaur)
+ _ S_chain (iron chain)
+ # S_cloud (cloud)
+ c S_cockatrice (cockatrice)
+ $ S_coin (pile of coins)
+ # S_corr (corridor)
+ - S_crwall (wall)
+ # S_darkroom (dark room)
+ ^ S_dart_trap (dart trap)
+ & S_demon (major demon)
+ * S_digbeam (dig beam)
+ > S_dnladder (ladder down)
+ > S_dnstair (staircase down)
+ d S_dog (dog or other canine)
+ D S_dragon (dragon)
+ ; S_eel (sea monster)
+ E S_elemental (elemental)
+ / S_explode1 (explosion top left)
+ - S_explode2 (explosion top center)
+ \ S_explode3 (explosion top right)
+ | S_explode4 (explosion middle left)
+ S_explode5 (explosion middle center)
+ | S_explode6 (explosion middle right)
+ \ S_explode7 (explosion bottom left)
+ - S_explode8 (explosion bottom center)
+ / S_explode9 (explosion bottom right)
+ e S_eye (eye or sphere)
+
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 79
+
+
+
+ ^ S_falling_rock_trap (falling rock trap)
+ f S_feline (cat or other feline)
+ ^ S_fire_trap (fire trap)
+ ! S_flashbeam (flash beam)
+ % S_food (piece of food)
+ { S_fountain (fountain)
+ F S_fungus (fungus or mold)
+ * S_gem (gem or rock)
+ S_ghost (ghost)
+ H S_giant (giant humanoid)
+ G S_gnome (gnome)
+ ' S_golem (golem)
+ | S_grave (grave)
+ g S_gremlin (gremlin)
+ - S_hbeam (horizontal beam [zap animation])
+ # S_hcdbridge (horizontal raised drawbridge)
+ + S_hcdoor (closed door in horizontal wall)
+ . S_hodbridge (horizontal lowered drawbridge)
+ | S_hodoor (open door in horizontal wall)
+ ^ S_hole (hole)
+ @ S_human (human or elf)
+ h S_humanoid (humanoid)
+ - S_hwall (horizontal wall)
+ . S_ice (ice)
+ i S_imp (imp or minor demon)
+ I S_invisible (invisible monster)
+ J S_jabberwock (jabberwock)
+ j S_jelly (jelly)
+ k S_kobold (kobold)
+ K S_kop (Keystone Kop)
+ ^ S_land_mine (land mine)
+ } S_lava (molten lava)
+ l S_leprechaun (leprechaun)
+ ^ S_level_teleporter (level teleporter)
+ L S_lich (lich)
+ y S_light (light)
+ # S_litcorr (lit corridor)
+ : S_lizard (lizard)
+ \ S_lslant (diagonal beam [zap animation])
+ ^ S_magic_portal (magic portal)
+ ^ S_magic_trap (magic trap)
+ m S_mimic (mimic)
+ ] S_mimic_def (mimic)
+ M S_mummy (mummy)
+ N S_naga (naga)
+ . S_ndoor (doorway without door)
+ n S_nymph (nymph)
+ O S_ogre (ogre)
+ o S_orc (orc)
+ p S_piercer (piercer)
+ ^ S_pit (pit)
+ # S_poisoncloud (poison cloud)
+ ^ S_polymorph_trap (polymorph trap)
+
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 80
+
+
+
+ } S_pool (water)
+ ! S_potion (potion)
+ P S_pudding (pudding or ooze)
+ q S_quadruped (quadruped)
+ Q S_quantmech (quantum mechanic)
+ = S_ring (ring)
+ ` S_rock (boulder or statue)
+ r S_rodent (rodent)
+ ^ S_rolling_boulder_trap (rolling boulder trap)
+ . S_room (floor of a room)
+ / S_rslant (diagonal beam [zap animation])
+ ^ S_rust_trap (rust trap)
+ R S_rustmonst (rust monster or disenchanter)
+ ? S_scroll (scroll)
+ # S_sink (sink)
+ ^ S_sleeping_gas_trap (sleeping gas trap)
+ S S_snake (snake)
+ s S_spider (arachnid or centipede)
+ ^ S_spiked_pit (spiked pit)
+ ^ S_squeaky_board (squeaky board)
+ 0 S_ss1 (magic shield 1 of 4)
+ # S_ss2 (magic shield 2 of 4)
+ @ S_ss3 (magic shield 3 of 4)
+ * S_ss4 (magic shield 4 of 4)
+ ^ S_statue_trap (statue trap)
+ S_stone (solid rock or unexplored terrain
+ or dark part of a room)
+ ] S_strange_obj (strange object)
+ - S_sw_bc (swallow bottom center)
+ \ S_sw_bl (swallow bottom left)
+ / S_sw_br (swallow bottom right)
+ | S_sw_ml (swallow middle left)
+ | S_sw_mr (swallow middle right)
+ - S_sw_tc (swallow top center)
+ / S_sw_tl (swallow top left)
+ \ S_sw_tr (swallow top right)
+ - S_tdwall (wall)
+ ^ S_teleportation_trap (teleportation trap)
+ \ S_throne (opulent throne)
+ - S_tlcorn (top left corner)
+ | S_tlwall (wall)
+ ( S_tool (useful item (pick-axe, key, lamp...))
+ ^ S_trap_door (trap door)
+ t S_trapper (trapper or lurker above)
+ - S_trcorn (top right corner)
+ # S_tree (tree)
+ T S_troll (troll)
+ | S_trwall (wall)
+ - S_tuwall (wall)
+ U S_umber (umber hulk)
+ u S_unicorn (unicorn or horse)
+ < S_upladder (ladder up)
+ < S_upstair (staircase up)
+
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 81
+
+
+
+ V S_vampire (vampire)
+ | S_vbeam (vertical beam [zap animation])
+ # S_vcdbridge (vertical raised drawbridge)
+ + S_vcdoor (closed door in vertical wall)
+ . S_venom (splash of venom)
+ ^ S_vibrating_square (vibrating square)
+ . S_vodbridge (vertical lowered drawbridge)
+ - S_vodoor (open door in vertical wall)
+ v S_vortex (vortex)
+ | S_vwall (vertical wall)
+ / S_wand (wand)
+ } S_water (water)
+ ) S_weapon (weapon)
+ " S_web (web)
+ w S_worm (worm)
+ ~ S_worm_tail (long worm tail)
+ W S_wraith (wraith)
+ x S_xan (xan or other extraordinary insect)
+ X S_xorn (xorn)
+ Y S_yeti (apelike creature)
+ Z S_zombie (zombie)
+ z S_zruty (zruty)
+ S_pet_override (any pet if ACCESSIBILITY=1 is set)
+ S_hero_override (hero if ACCESSIBILITY=1 is set)
+
+ Notes:
+
+ * Several symbols in this table appear to be blank. They are the
+ space character, except for S_pet_override and S_hero_override which
+ don't have any default value and can only be used if enabled in the
+ "sysconf" file.
+
+ * S_rock is misleadingly named; rocks and stones use S_gem. Statues
+ and boulders are the rock being referred to, but since version
+ 3.6.0, statues are displayed as the monster they depict. So S_rock
+ is only used for boulders and not used at all if overridden by the
+ more specific S_boulder.
+
+ 9.15. Configuring NetHack for Play by the Blind
+
+ NetHack can be set up to use only standard ASCII characters for
+ making maps of the dungeons. This makes the MS-DOS versions of NetHack
+ completely accessible to the blind who use speech and/or Braille
+ access technologies. Players will require a good working knowledge of
+ their screen-reader's review features, and will have to know how to
+ navigate horizontally and vertically character by character. They will
+ also find the search capabilities of their screen-readers to be quite
+ valuable. Be certain to examine this Guidebook before playing so you
+ have an idea what the screen layout is like. You'll also need to be
+ able to locate the PC cursor. It is always where your character is
+ located. Merely searching for an @-sign will not always find your
+ character since there are other humanoids represented by the same
+ sign. Your screen-reader should also have a function which gives you
+ the row and column of your review cursor and the PC cursor. These co-
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 82
+
+
+
+ ordinates are often useful in giving players a better sense of the
+ overall location of items on the screen.
+
+ NetHack can also be compiled with support for sending the game
+ messages to an external program, such as a text-to-speech synthesizer.
+ If the "#version" extended command shows "external program as a mes-
+ sage handler", your NetHack has been compiled with the capability.
+ When compiling NetHack from source on Linux and other POSIX systems,
+ define MSGHANDLER to enable it. To use the capability, set the envi-
+ ronment variable NETHACK_MSGHANDLER to an executable, which will be
+ executed with the game message as the program's only parameter.
+
+ While it is not difficult for experienced users to edit the
+ defaults.nh file to accomplish this, novices may find this task some-
+ what daunting. Included within the "symbols" file of all official
+ distributions of NetHack is a symset called NHAccess. Selecting that
+ symset in your configuration file will cause the game to run in a man-
+ ner accessible to the blind. After you have gained some experience
+ with the game and with editing files, you may want to alter settings
+ via SYMBOLS= and ROGUESYMBOLS= in your configuration file to better
+ suit your preferences. See the previous section for the special sym-
+ bols S_pet_override to force a consistent symbol for all pets and
+ S_hero_override to force a unique symbol for the player character if
+ accessibility is enabled in the sysconf file.
+
+ The most crucial settings to make the game more accessible are:
+
+ symset:NHAccess
+ Load a symbol set appropriate for use by blind players.
+
+ roguesymset:NHAccess
+ Load a symbol set for the rogue level that is appropriate for use by
+ blind players.
+
+ menustyle:traditional
+ This will assist in the interface to speech synthesizers.
+
+ nomenu_overlay
+ Show menus on a cleared screen and aligned to the left edge.
+
+ number_pad
+ A lot of speech access programs use the number-pad to review the
+ screen. If this is the case, disable the number_pad option and use
+ the traditional Rogue-like commands.
+
+ autodescribe
+ Automatically describe the terrain under the cursor when targeting.
+
+ mention_walls
+ Give feedback messages when walking towards a wall or when travel
+ command was interrupted.
+
+ whatis_coord:compass
+ When targeting with cursor, describe the cursor position with coor-
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 83
+
+
+
+ dinates relative to your character.
+
+ whatis_filter:area
+ When targeting with cursor, filter possible locations so only those
+ in the same area (eg. same room, or same corridor) are considered.
+
+ whatis_moveskip
+ When targeting with cursor and using fast-move, skip the same glyphs
+ instead of moving 8 units at a time.
+
+ nostatus_updates
+ Prevent updates to the status lines at the bottom of the screen, if
+ your screen-reader reads those lines. The same information can be
+ seen via the "#attributes" command.
+
+ 9.16. Global Configuration for System Administrators
+
+ If NetHack is compiled with the SYSCF option, a system adminis-
+ trator should set up a global configuration; this is a file in the
+ same format as the traditional per-user configuration file (see
+ above). This file should be named sysconf and placed in the same
+ directory as the other NetHack support files. The options recognized
+ in this file are listed below. Any option not set uses a compiled-in
+ default (which may not be appropriate for your system).
+
+ WIZARDS = A space-separated list of user names who are allowed to
+ play in debug mode (commonly referred to as wizard mode). A value
+ of a single asterisk (*) allows anyone to start a game in debug
+ mode.
+
+ SHELLERS = A list of users who are allowed to use the shell escape
+ command (!). The syntax is the same as WIZARDS.
+
+ EXPLORERS = A list of users who are allowed to use the explore mode.
+ The syntax is the same as WIZARDS.
+
+ MAXPLAYERS = Limit the maximum number of games that can be running
+ at the same time.
+
+ SUPPORT = A string explaining how to get local support (no default
+ value).
+
+ RECOVER = A string explaining how to recover a game on this system
+ (no default value).
+
+ SEDUCE = 0 or 1 to disable or enable, respectively, the SEDUCE
+ option. When disabled, incubi and succubi behave like nymphs.
+
+ CHECK_PLNAME = Setting this to 1 will make the EXPLORERS, WIZARDS,
+ and SHELLERS check for the player name instead of the user's login
+ name.
+
+ CHECK_SAVE_UID = 0 or 1 to disable or enable, respectively, the UID
+ (used identification number) checking for save files (to verify that
+
+
+ NetHack 3.6.7 February 3, 2023
+
+
+
+
+
+ NetHack Guidebook 84
+
+
+
+ the user who is restoring is the same one who saved).
+
+ The following options affect the score file:
+
+ PERSMAX = Maximum number of entries for one person.
+
+ ENTRYMAX = Maximum number of entries in the score file.
+
+ POINTSMIN = Minimum number of points to get an entry in the score
+ file.
+
+ PERS_IS_UID = 0 or 1 to use user names or numeric userids, respec-
+ tively, to identify unique people for the score file.
+
+ MAX_STATUENAME_RANK = Maximum number of score file entries to use
+ for random statue names (default is 10).
+
+ ACCESSIBILITY = 0 or 1 to disable or enable, respectively, the abil-
+ ity for players to set S_pet_override and S_hero_override symbols in
+ their configuration file.
+
+ PORTABLE_DEVICE_PATHS = 0 or 1 Windows OS only, the game will look
+ for all of its external files, and write to all of its output files
+ in one place rather than at the standard locations.
+
+ DUMPLOGFILE = A filename where the end-of-game dumplog is saved.
+ Not defining this will prevent dumplog from being created. Only
+ available if your game is compiled with DUMPLOG. Allows the follow-
+ ing placeholders:
- The pattern should be a POSIX extended regular expression.
+ %% - literal `%'
+ %v - version (eg. "3.6.3-0")
+ %u - game UID
+ %t - game start time, UNIX timestamp format
+ %T - current time, UNIX timestamp format
+ %d - game start time, YYYYMMDDhhmmss format
+ %D - current time, YYYYMMDDhhmmss format
+ %n - player name
+ %N - first character of player name
- 9.13. Configuring Status Hilites
+ 10. Scoring
- Your copy of NetHack may have been compiled with support for
- "Status Hilites". If so, you can customize your game display by
- setting thresholds to change the color or appearance of fields in
- the status display.
+ NetHack maintains a list of the top scores or scorers on your
+ machine, depending on how it is set up. In the latter case, each
+ account on the machine can post only one non-winning score on this
+ list. If you score higher than someone else on this list, or better
+ your previous score, you will be inserted in the proper place under
+ your current name. How many scores are kept can also be set up when
+ NetHack is compiled.
- The format for defining status colors is:
+ Your score is chiefly based upon how much experience you gained,
+ how much loot you accumulated, how deep you explored, and how the game
+ ended. If you quit the game, you escape with all of your gold intact.
+ If, however, you get killed in the Mazes of Menace, the guild will
- OPTION=hilite_status:field-name/behavior/color&attributes
- For example, the following line in your configuration file
- will cause the hitpoints field to display in the color red if
- your hitpoints drop to or below a threshold of 30%:
+ NetHack 3.6.7 February 3, 2023
- OPTION=hilite_status:hitpoints/<=30%/red/normal
- (That example is actually specifying red&normal for <=30% and no-
- color&normal for >30%.)
- For another example, the following line in your configura-
- tion file will cause wisdom to be displayed red if it drops and
- green if it rises:
- OPTION=hilite_status:wisdom/down/red/up/green
- Allowed colors are black, red, green, brown, blue, magenta,
- cyan, gray, orange, light-green, yellow, light-blue, light-
+ NetHack Guidebook 85
- NetHack 3.6 March 4, 2020
+ only hear about 90% of your gold when your corpse is discovered
+ (adventurers have been known to collect finder's fees). So, consider
+ whether you want to take one last hit at that monster and possibly
+ live, or quit and stop with whatever you have. If you quit, you keep
+ all your gold, but if you swing and live, you might find more.
+ If you just want to see what the current top players/games list
+ is, you can type nethack -s all on most versions.
+ 11. Explore mode
+ NetHack is an intricate and difficult game. Novices might falter
+ in fear, aware of their ignorance of the means to survive. Well, fear
+ not. Your dungeon comes equipped with an "explore" or "discovery"
+ mode that enables you to keep old save files and cheat death, at the
+ paltry cost of not getting on the high score list.
- NetHack Guidebook 77
+ There are two ways of enabling explore mode. One is to start the
+ game with the -X command-line switch or with the playmode:explore
+ option. The other is to issue the "#exploremode" extended command
+ while already playing the game. Starting a new game in explore mode
+ provides your character with a wand of wishing in initial inventory;
+ switching during play does not. The other benefits of explore mode
+ are left for the trepid reader to discover.
+ 11.1. Debug mode
+ Debug mode, also known as wizard mode, is undocumented aside from
+ this brief description and the various "debug mode only" commands
+ listed among the command descriptions. It is intended for tracking
+ down problems within the program rather than to provide god-like pow-
+ ers to your character, and players who attempt debugging are expected
+ to figure out how to use it themselves. It is initiated by starting
+ the game with the -D command-line switch or with the playmode:debug
+ option.
- magenta, light-cyan, and white. And "no-color", the default
- foreground color on the display, which is not necessarily the
- same as black or white or any of the other colors.
+ For some systems, the player must be logged in under a particular
+ user name to be allowed to use debug mode; for others, the hero must
+ be given a particular character name (but may be any role; there's no
+ connection between "wizard mode" and the Wizard role). Attempting to
+ start a game in debug mode when not allowed or not available will
+ result in falling back to explore mode instead.
- Allowed attributes are none, bold, dim, underline, blink,
- and inverse. "Normal" is a synonym for "none"; they should not
- be used in combination with any of the other attributes.
+ 12. Credits
- To specify both a color and an attribute, use `&' to combine
- them. To specify multiple attributes, use `+' to combine those.
- For example: "magenta&inverse+dim".
+ The original hack game was modeled on the Berkeley UNIX rogue
+ game. Large portions of this paper were shamelessly cribbed from A
+ Guide to the Dungeons of Doom, by Michael C. Toy and Kenneth C. R. C.
+ Arnold. Small portions were adapted from Further Exploration of the
+ Dungeons of Doom, by Ken Arromdee.
- Note that the display may substitute or ignore particular
- attributes depending upon its capabilities, and in general may
- interpret the attributes any way it wants. For example, on some
- display systems a request for bold might yield blink or vice ver-
- sa. On others, issuing an attribute request while another is al-
- ready set up will replace the earlier attribute rather than com-
- bine with it. Since NetHack issues attribute requests sequen-
- tially (at least with the tty interface) rather than all at once,
- the only way a situation like that can be controlled is to speci-
- fy just one attribute.
+ NetHack is the product of literally dozens of people's work.
+ Main events in the course of the game development are described below:
- You can adjust the appearance of the following status
- fields:
- title dungeon-level experience-level
- strength gold experience
- dexterity hitpoints HD
- constitution hitpoints-max time
- intelligence power hunger
- wisdom power-max carrying-capacity
- charisma armor-class condition
- alignment score
- The pseudo-field "characteristics" can be used to set all six
- of Str, Dex, Con, Int, Wis, and Cha at once. "HD" is "hit
- dice", an approximation of experience level displayed when
- polymorphed. "experience", "time", and "score" are condition-
- ally displayed depending upon your other option settings.
- Instead of a behavior, "condition" takes the following condi-
- tion flags: stone, slime, strngl, foodpois, termill, blind,
- deaf, stun, conf, hallu, lev, fly, and ride. You can use "ma-
- jor_troubles" as an alias for stone through termill, "mi-
- nor_troubles" for blind through hallu, "movement" for lev, fly,
- and ride, and "all" for every condition.
+ NetHack 3.6.7 February 3, 2023
- Allowed behaviors are "always", "up", "down", "changed", a per-
- centage or absolute number threshold, or text to match against.
- * "always" will set the default attributes for that field.
- * "up", "down" set the field attributes for when the field
- value changes upwards or downwards. This attribute times
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 86
+ Jay Fenlason wrote the original Hack, with help from Kenny Wood-
+ land, Mike Thome and Jon Payne.
+ Andries Brouwer did a major re-write, transforming Hack into a
+ very different game, and published (at least) three versions (1.0.1,
+ 1.0.2, and 1.0.3) for UNIX machines to the Usenet.
- NetHack Guidebook 78
+ Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS, pro-
+ ducing PC HACK 1.01e, added support for DEC Rainbow graphics in ver-
+ sion 1.03g, and went on to produce at least four more versions (3.0,
+ 3.2, 3.51, and 3.6).
+ R. Black ported PC HACK 3.51 to Lattice C and the Atari
+ 520/1040ST, producing ST Hack 1.03.
+ Mike Stephenson merged these various versions back together,
+ incorporating many of the added features, and produced NetHack 1.4.
+ He then coordinated a cast of thousands in enhancing and debugging
+ NetHack 1.4 and released NetHack versions 2.2 and 2.3.
- out after statushilites turns.
+ Later, Mike coordinated a major rewrite of the game, heading a
+ team which included Ken Arromdee, Jean-Christophe Collet, Steve Creps,
+ Eric Hendrickson, Izchak Miller, John Rupley, Mike Threepoint, and
+ Janet Walz, to produce NetHack 3.0c.
- * "changed" sets the field attribute for when the field val-
- ue changes. This attribute times out after statushilites
- turns. (If a field has both a "changed" rule and an "up"
- or "down" rule which matches a change in the field's val-
- ue, the "up" or "down" one takes precedence.)
+ NetHack 3.0 was ported to the Atari by Eric R. Smith, to OS/2 by
+ Timo Hakulinen, and to VMS by David Gentzel. The three of them and
+ Kevin Darcy later joined the main NetHack Development Team to produce
+ subsequent revisions of 3.0.
- * percentage sets the field attribute when the field value
- matches the percentage. It is specified as a number be-
- tween 0 and 100, followed by `%' (percent sign). If the
- percentage is prefixed with `<=' or `>=', it also matches
- when value is below or above the percentage. Use prefix
- `<' or `>' to match when strictly below or above. (The
- numeric limit is relaxed slightly for those: >-1% and
- <101% are allowed.) Only four fields support percentage
- rules. Percentages for "hitpoints" and "power" are
- straightforward; they're based on the corresponding maxi-
- mum field. Percentage highlight rules are also allowed
- for "experience level" and "experience points" (valid when
- the showexp option is enabled). For those, the percentage
- is based on the progress from the start of the current ex-
- perience level to the start of the next level. So if lev-
- el 2 starts at 20 points and level 3 starts at 40 points,
- having 30 points is 50% and 35 points is 75%. 100% is
- unattainable for experience because you'll gain a level
- and the calculations will be reset for that new level, but
- a rule for =100% is allowed and matches the special case
- of being exactly 1 experience point short of the next lev-
- el.
+ Olaf Seibert ported NetHack 2.3 and 3.0 to the Amiga. Norm
+ Meluch, Stephen Spackman and Pierre Martineau designed overlay code
+ for PC NetHack 3.0. Johnny Lee ported NetHack 3.0 to the Macintosh.
+ Along with various other Dungeoneers, they continued to enhance the
+ PC, Macintosh, and Amiga ports through the later revisions of 3.0.
- * absolute value sets the attribute when the field value
- matches that number. The number must be 0 or higher, ex-
- cept for "armor-class' which allows negative values, and
- may optionally be preceded by `='. If the number is pre-
- ceded by `<=' or `>=' instead, it also matches when value
- is below or above. If the prefix is `<' or `>', only
- match when strictly above or below.
+ Headed by Mike Stephenson and coordinated by Izchak Miller and
+ Janet Walz, the NetHack Development Team which now included Ken
+ Arromdee, David Cohrs, Jean-Christophe Collet, Kevin Darcy, Matt Day,
+ Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Eric Raymond,
+ and Eric Smith undertook a radical revision of 3.0. They re-struc-
+ tured the game's design, and re-wrote major parts of the code. They
+ added multiple dungeons, a new display, special individual character
+ quests, a new endgame and many other new features, and produced
+ NetHack 3.1.
- * text match sets the attribute when the field value matches
- the text. Text matches can only be used for "alignment",
- "carrying-capacity", "hunger", "dungeon-level", and "ti-
- tle". For title, only the role's rank title is tested;
- the character's name is ignored.
+ Ken Lorber, Gregg Wonderly and Greg Olson, with help from Richard
+ Addison, Mike Passaretti, and Olaf Seibert, developed NetHack 3.1 for
+ the Amiga.
- The in-game options menu can help you determine the correct
- syntax for a configuration file.
+ Norm Meluch and Kevin Smolkowski, with help from Carl Schelin,
+ Stephen Spackman, Steve VanDevender, and Paul Winner, ported NetHack
+ 3.1 to the PC.
- The whole feature can be disabled by setting option sta-
- tushilites to 0.
- Example hilites:
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 87
- NetHack Guidebook 79
+ Jon W{tte and Hao-yang Wang, with help from Ross Brown, Mike Eng-
+ ber, David Hairston, Michael Hamel, Jonathan Handler, Johnny Lee, Tim
+ Lennan, Rob Menke, and Andy Swanson, developed NetHack 3.1 for the
+ Macintosh, porting it for MPW. Building on their development, Bart
+ House added a Think C port.
+ Timo Hakulinen ported NetHack 3.1 to OS/2. Eric Smith ported
+ NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua
+ Delahunty, was responsible for the VMS version of NetHack 3.1.
+ Michael Allison ported NetHack 3.1 to Windows NT.
+ Dean Luick, with help from David Cohrs, developed NetHack 3.1 for
+ X11. Warwick Allison wrote a tiled version of NetHack for the Atari;
+ he later contributed the tiles to the NetHack Development Team and
+ tile support was then added to other platforms.
- OPTION=hilite_status: gold/up/yellow/down/brown
- OPTION=hilite_status: characteristics/up/green/down/red
- OPTION=hilite_status: hitpoints/100%/gray&normal
- OPTION=hilite_status: hitpoints/<100%/green&normal
- OPTION=hilite_status: hitpoints/<66%/yellow&normal
- OPTION=hilite_status: hitpoints/<50%/orange&normal
- OPTION=hilite_status: hitpoints/<33%/red&bold
- OPTION=hilite_status: hitpoints/<15%/red&inverse
- OPTION=hilite_status: condition/major/orange&inverse
- OPTION=hilite_status: condition/lev+fly/red&inverse
+ The 3.2 NetHack Development Team, comprised of Michael Allison,
+ Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy,
+ Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Eric Smith,
+ Mike Stephenson, Janet Walz, and Paul Winner, released version 3.2 in
+ April of 1996.
- 9.14. Modifying NetHack Symbols
+ Version 3.2 marked the tenth anniversary of the formation of the
+ development team. In a testament to their dedication to the game, all
+ thirteen members of the original NetHack Development Team remained on
+ the team at the start of work on that release. During the interval
+ between the release of 3.1.3 and 3.2, one of the founding members of
+ the NetHack Development Team, Dr. Izchak Miller, was diagnosed with
+ cancer and passed away. That release of the game was dedicated to him
+ by the development and porting teams.
- NetHack can load entire symbol sets from the symbol file.
+ During the lifespan of NetHack 3.1 and 3.2, several enthusiasts
+ of the game added their own modifications to the game and made these
+ "variants" publicly available:
- The options that are used to select a particular symbol set
- from the symbol file are:
-
- symset
- Set the name of the symbol set that you want to load.
-
- roguesymset
- Set the name of the symbol set that you want to load for dis-
- play on the rogue level.
+ Tom Proudfoot and Yuval Oren created NetHack++, which was quickly
+ renamed NetHack--. Working independently, Stephen White wrote NetHack
+ Plus. Tom Proudfoot later merged NetHack Plus and his own NetHack--
+ to produce SLASH. Larry Stewart-Zerba and Warwick Allison improved
+ the spell casting system with the Wizard Patch. Warwick Allison also
+ ported NetHack to use the Qt interface.
- You can also override one or more symbols using the SYMBOLS
- and ROGUESYMBOLS configuration file options. Symbols are speci-
- fied as name:value pairs. Note that NetHack escape-processes the
- value string in conventional C fashion. This means that \ is a
- prefix to take the following character literally. Thus \ needs
- to be represented as \\. The special prefix form \m switches on
- the meta bit in the symbol value, and the ^ prefix causes the
- following character to be treated as a control character.
-
- NetHack Symbols
- Symbol Name Description
- -----------------------------------------------------------------
- S_air (air)
- _ S_altar (altar)
- " S_amulet (amulet)
- A S_angel (angelic being)
- a S_ant (ant or other insect)
- ^ S_anti_magic_trap (anti-magic field)
- [ S_armor (suit or piece of armor)
- [ S_armour (suit or piece of armor)
- ^ S_arrow_trap (arrow trap)
- 0 S_ball (iron ball)
- # S_bars (iron bars)
- B S_bat (bat or bird)
- ^ S_bear_trap (bear trap)
- - S_blcorn (bottom left corner)
- b S_blob (blob)
- + S_book (spellbook)
-
-
-
- NetHack 3.6 March 4, 2020
-
-
-
-
-
- NetHack Guidebook 80
-
-
-
- ) S_boomleft (boomerang open left)
- ( S_boomright (boomerang open right)
- ` S_boulder (boulder)
- - S_brcorn (bottom right corner)
- C S_centaur (centaur)
- _ S_chain (iron chain)
- # S_cloud (cloud)
- c S_cockatrice (cockatrice)
- $ S_coin (pile of coins)
- # S_corr (corridor)
- - S_crwall (wall)
- # S_darkroom (dark room)
- ^ S_dart_trap (dart trap)
- & S_demon (major demon)
- * S_digbeam (dig beam)
- > S_dnladder (ladder down)
- > S_dnstair (staircase down)
- d S_dog (dog or other canine)
- D S_dragon (dragon)
- ; S_eel (sea monster)
- E S_elemental (elemental)
- / S_explode1 (explosion top left)
- - S_explode2 (explosion top center)
- \ S_explode3 (explosion top right)
- | S_explode4 (explosion middle left)
- S_explode5 (explosion middle center)
- | S_explode6 (explosion middle right)
- \ S_explode7 (explosion bottom left)
- - S_explode8 (explosion bottom center)
- / S_explode9 (explosion bottom right)
- e S_eye (eye or sphere)
- ^ S_falling_rock_trap (falling rock trap)
- f S_feline (cat or other feline)
- ^ S_fire_trap (fire trap)
- ! S_flashbeam (flash beam)
- % S_food (piece of food)
- { S_fountain (fountain)
- F S_fungus (fungus or mold)
- * S_gem (gem or rock)
- S_ghost (ghost)
- H S_giant (giant humanoid)
- G S_gnome (gnome)
- ' S_golem (golem)
- | S_grave (grave)
- g S_gremlin (gremlin)
- - S_hbeam (horizontal beam [zap animation])
- # S_hcdbridge (horizontal raised drawbridge)
- + S_hcdoor (closed door in horizontal wall)
- . S_hodbridge (horizontal lowered drawbridge)
- | S_hodoor (open door in horizontal wall)
- ^ S_hole (hole)
- @ S_human (human or elf)
- h S_humanoid (humanoid)
-
-
-
- NetHack 3.6 March 4, 2020
-
-
-
-
-
- NetHack Guidebook 81
-
-
-
- - S_hwall (horizontal wall)
- . S_ice (ice)
- i S_imp (imp or minor demon)
- I S_invisible (invisible monster)
- J S_jabberwock (jabberwock)
- j S_jelly (jelly)
- k S_kobold (kobold)
- K S_kop (Keystone Kop)
- ^ S_land_mine (land mine)
- } S_lava (molten lava)
- l S_leprechaun (leprechaun)
- ^ S_level_teleporter (level teleporter)
- L S_lich (lich)
- y S_light (light)
- # S_litcorr (lit corridor)
- : S_lizard (lizard)
- \ S_lslant (diagonal beam [zap animation])
- ^ S_magic_portal (magic portal)
- ^ S_magic_trap (magic trap)
- m S_mimic (mimic)
- ] S_mimic_def (mimic)
- M S_mummy (mummy)
- N S_naga (naga)
- . S_ndoor (doorway without door)
- n S_nymph (nymph)
- O S_ogre (ogre)
- o S_orc (orc)
- p S_piercer (piercer)
- ^ S_pit (pit)
- # S_poisoncloud (poison cloud)
- ^ S_polymorph_trap (polymorph trap)
- } S_pool (water)
- ! S_potion (potion)
- P S_pudding (pudding or ooze)
- q S_quadruped (quadruped)
- Q S_quantmech (quantum mechanic)
- = S_ring (ring)
- ` S_rock (boulder or statue)
- r S_rodent (rodent)
- ^ S_rolling_boulder_trap (rolling boulder trap)
- . S_room (floor of a room)
- / S_rslant (diagonal beam [zap animation])
- ^ S_rust_trap (rust trap)
- R S_rustmonst (rust monster or disenchanter)
- ? S_scroll (scroll)
- # S_sink (sink)
- ^ S_sleeping_gas_trap (sleeping gas trap)
- S S_snake (snake)
- s S_spider (arachnid or centipede)
- ^ S_spiked_pit (spiked pit)
- ^ S_squeaky_board (squeaky board)
- 0 S_ss1 (magic shield 1 of 4)
- # S_ss2 (magic shield 2 of 4)
-
-
-
- NetHack 3.6 March 4, 2020
-
-
-
-
-
- NetHack Guidebook 82
-
-
-
- @ S_ss3 (magic shield 3 of 4)
- * S_ss4 (magic shield 4 of 4)
- ^ S_statue_trap (statue trap)
- S_stone (solid rock or unexplored terrain
- or dark part of a room)
- ] S_strange_obj (strange object)
- - S_sw_bc (swallow bottom center)
- \ S_sw_bl (swallow bottom left)
- / S_sw_br (swallow bottom right)
- | S_sw_ml (swallow middle left)
- | S_sw_mr (swallow middle right)
- - S_sw_tc (swallow top center)
- / S_sw_tl (swallow top left)
- \ S_sw_tr (swallow top right)
- - S_tdwall (wall)
- ^ S_teleportation_trap (teleportation trap)
- \ S_throne (opulent throne)
- - S_tlcorn (top left corner)
- | S_tlwall (wall)
- ( S_tool (useful item (pick-axe, key, lamp...))
- ^ S_trap_door (trap door)
- t S_trapper (trapper or lurker above)
- - S_trcorn (top right corner)
- # S_tree (tree)
- T S_troll (troll)
- | S_trwall (wall)
- - S_tuwall (wall)
- U S_umber (umber hulk)
- u S_unicorn (unicorn or horse)
- < S_upladder (ladder up)
- < S_upstair (staircase up)
- V S_vampire (vampire)
- | S_vbeam (vertical beam [zap animation])
- # S_vcdbridge (vertical raised drawbridge)
- + S_vcdoor (closed door in vertical wall)
- . S_venom (splash of venom)
- ^ S_vibrating_square (vibrating square)
- . S_vodbridge (vertical lowered drawbridge)
- - S_vodoor (open door in vertical wall)
- v S_vortex (vortex)
- | S_vwall (vertical wall)
- / S_wand (wand)
- } S_water (water)
- ) S_weapon (weapon)
- " S_web (web)
- w S_worm (worm)
- ~ S_worm_tail (long worm tail)
- W S_wraith (wraith)
- x S_xan (xan or other extraordinary insect)
- X S_xorn (xorn)
- Y S_yeti (apelike creature)
- Z S_zombie (zombie)
- z S_zruty (zruty)
-
-
-
- NetHack 3.6 March 4, 2020
-
-
-
-
-
- NetHack Guidebook 83
-
-
-
- S_pet_override (any pet if ACCESSIBILITY=1 is set)
- S_hero_override (hero if ACCESSIBILITY=1 is set)
-
- Notes:
-
- * Several symbols in this table appear to be blank. They are the
- space character, except for S_pet_override and S_hero_override
- which don't have any default value and can only be used if en-
- abled in the "sysconf" file.
+ Warren Cheung combined SLASH with the Wizard Patch to produce
+ Slash'EM, and with the help of Kevin Hugo, added more features. Kevin
+ later joined the NetHack Development Team and incorporated the best of
+ these ideas in NetHack 3.3.
- * S_rock is misleadingly named; rocks and stones use S_gem.
- Statues and boulders are the rock being referred to, but since
- version 3.6.0, statues are displayed as the monster they de-
- pict. So S_rock is only used for boulders and not used at all
- if overridden by the more specific S_boulder.
+ The final update to 3.2 was the bug fix release 3.2.3, which was
+ released simultaneously with 3.3.0 in December 1999 just in time for
+ the Year 2000.
- 9.15. Configuring NetHack for Play by the Blind
+ The 3.3 NetHack Development Team, consisting of Michael Allison,
+ Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy,
+ Timo Hakulinen, Kevin Hugo, Steve Linhart, Ken Lorber, Dean Luick, Pat
- NetHack can be set up to use only standard ASCII characters
- for making maps of the dungeons. This makes the MS-DOS versions
- of NetHack completely accessible to the blind who use speech
- and/or Braille access technologies. Players will require a good
- working knowledge of their screen-reader's review features, and
- will have to know how to navigate horizontally and vertically
- character by character. They will also find the search capabili-
- ties of their screen-readers to be quite valuable. Be certain to
- examine this Guidebook before playing so you have an idea what
- the screen layout is like. You'll also need to be able to locate
- the PC cursor. It is always where your character is located.
- Merely searching for an @-sign will not always find your charac-
- ter since there are other humanoids represented by the same sign.
- Your screen-reader should also have a function which gives you
- the row and column of your review cursor and the PC cursor.
- These co-ordinates are often useful in giving players a better
- sense of the overall location of items on the screen.
- NetHack can also be compiled with support for sending the
- game messages to an external program, such as a text-to-speech
- synthesizer. If the "#version" extended command shows "external
- program as a message handler", your NetHack has been compiled
- with the capability. When compiling NetHack from source on Linux
- and other POSIX systems, define MSGHANDLER to enable it. To use
- the capability, set the environment variable NETHACK_MSGHANDLER
- to an executable, which will be executed with the game message as
- the program's only parameter.
+ NetHack 3.6.7 February 3, 2023
- While it is not difficult for experienced users to edit the
- defaults.nh file to accomplish this, novices may find this task
- somewhat daunting. Included within the "symbols" file of all of-
- ficial distributions of NetHack is a symset called NHAccess. Se-
- lecting that symset in your configuration file will cause the
- game to run in a manner accessible to the blind. After you have
- gained some experience with the game and with editing files, you
- may want to alter settings via SYMBOLS= and ROGUESYMBOLS= in your
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 88
- NetHack Guidebook 84
+ Rankin, Eric Smith, Mike Stephenson, Janet Walz, and Paul Winner,
+ released 3.3.0 in December 1999 and 3.3.1 in August of 2000.
+ Version 3.3 offered many firsts. It was the first version to sep-
+ arate race and profession. The Elf class was removed in preference to
+ an elf race, and the races of dwarves, gnomes, and orcs made their
+ first appearance in the game alongside the familiar human race. Monk
+ and Ranger roles joined Archeologists, Barbarians, Cavemen, Healers,
+ Knights, Priests, Rogues, Samurai, Tourists, Valkyries and of course,
+ Wizards. It was also the first version to allow you to ride a steed,
+ and was the first version to have a publicly available web-site list-
+ ing all the bugs that had been discovered. Despite that constantly
+ growing bug list, 3.3 proved stable enough to last for more than a
+ year and a half.
+ The 3.4 NetHack Development Team initially consisted of Michael
+ Allison, Ken Arromdee, David Cohrs, Jessie Collet, Kevin Hugo, Ken
+ Lorber, Dean Luick, Pat Rankin, Mike Stephenson, Janet Walz, and Paul
+ Winner, with Warwick Allison joining just before the release of
+ NetHack 3.4.0 in March 2002.
- configuration file to better suit your preferences. See the pre-
- vious section for the special symbols S_pet_override to force a
- consistent symbol for all pets and S_hero_override to force a
- unique symbol for the player character if accessibility is en-
- abled in the sysconf file.
+ As with version 3.3, various people contributed to the game as a
+ whole as well as supporting ports on the different platforms that
+ NetHack runs on:
- The most crucial settings to make the game more accessible
- are:
+ Pat Rankin maintained 3.4 for VMS.
- symset:NHAccess
- Load a symbol set appropriate for use by blind players.
+ Michael Allison maintained NetHack 3.4 for the MS-DOS platform.
+ Paul Winner and Yitzhak Sapir provided encouragement.
- roguesymset:NHAccess
- Load a symbol set for the rogue level that is appropriate for
- use by blind players.
+ Dean Luick, Mark Modrall, and Kevin Hugo maintained and enhanced
+ the Macintosh port of 3.4.
- menustyle:traditional
- This will assist in the interface to speech synthesizers.
+ Michael Allison, David Cohrs, Alex Kompel, Dion Nicolaas, and
+ Yitzhak Sapir maintained and enhanced 3.4 for the Microsoft Windows
+ platform. Alex Kompel contributed a new graphical interface for the
+ Windows port. Alex Kompel also contributed a Windows CE port for
+ 3.4.1.
- nomenu_overlay
- Show menus on a cleared screen and aligned to the left edge.
+ Ron Van Iwaarden was the sole maintainer of NetHack for OS/2 the
+ past several releases. Unfortunately Ron's last OS/2 machine stopped
+ working in early 2006. A great many thanks to Ron for keeping NetHack
+ alive on OS/2 all these years.
- number_pad
- A lot of speech access programs use the number-pad to review
- the screen. If this is the case, disable the number_pad option
- and use the traditional Rogue-like commands.
+ Janne Salmijarvi and Teemu Suikki maintained and enhanced the
+ Amiga port of 3.4 after Janne Salmijarvi resurrected it for 3.3.1.
- autodescribe
- Automatically describe the terrain under the cursor when tar-
- geting.
+ Christian "Marvin" Bressler maintained 3.4 for the Atari after he
+ resurrected it for 3.3.1.
- mention_walls
- Give feedback messages when walking towards a wall or when
- travel command was interrupted.
+ The release of NetHack 3.4.3 in December 2003 marked the begin-
+ ning of a long release hiatus. 3.4.3 proved to be a remarkably stable
+ version that provided continued enjoyment by the community for more
+ than a decade. The NetHack Development Team slowly and quietly contin-
- whatis_coord:compass
- When targeting with cursor, describe the cursor position with
- coordinates relative to your character.
- whatis_filter:area
- When targeting with cursor, filter possible locations so only
- those in the same area (eg. same room, or same corridor) are
- considered.
+ NetHack 3.6.7 February 3, 2023
- whatis_moveskip
- When targeting with cursor and using fast-move, skip the same
- glyphs instead of moving 8 units at a time.
- nostatus_updates
- Prevent updates to the status lines at the bottom of the
- screen, if your screen-reader reads those lines. The same in-
- formation can be seen via the "#attributes" command.
+ NetHack Guidebook 89
- NetHack 3.6 March 4, 2020
+ ued to work on the game behind the scenes during the tenure of 3.4.3.
+ It was during that same period that several new variants emerged
+ within the NetHack community. Notably sporkhack by Derek S. Ray,
+ unnethack by Patric Mueller, nitrohack and its successors originally
+ by Daniel Thaler and then by Alex Smith, and Dynahack by Tung Nguyen.
+ Some of those variants continue to be developed, maintained, and
+ enjoyed by the community to this day.
+ In September 2014, an interim snapshot of the code under develop-
+ ment was released publicly by other parties. Since that code was a
+ work-in-progress and had not gone through the process of debugging it
+ as a suitable release, it was decided that the version numbers present
+ on that code snapshot would be retired and never used in an official
+ NetHack release. An announcement was posted on the NetHack Development
+ Team's official nethack.org website to that effect, stating that there
+ would never be a 3.4.4, 3.5, or 3.5.0 official release version.
+ In January 2015, preparation began for the release of NetHack
+ 3.6.
- NetHack Guidebook 85
+ At the beginning of development for what would eventually get
+ released as 3.6.0, the NetHack Development Team consisted of Warwick
+ Allison, Michael Allison, Ken Arromdee, David Cohrs, Jessie Collet,
+ Ken Lorber, Dean Luick, Pat Rankin, Mike Stephenson, Janet Walz, and
+ Paul Winner. In early 2015, ahead of the release of 3.6.0, new mem-
+ bers Sean Hunt, Pasi Kallinen, and Derek S. Ray joined the NetHack
+ Development Team.
+ Near the end of the development of 3.6.0, one of the significant
+ inspirations for many of the humorous and fun features found in the
+ game, author Terry Pratchett, passed away. NetHack 3.6.0 introduced a
+ tribute to him.
+ 3.6.0 was released in December 2015, and merged work done by the
+ development team since the release of 3.4.3 with some of the beloved
+ community patches. Many bugs were fixed and some code was restruc-
+ tured.
- 9.16. Global Configuration for System Administrators
+ The NetHack Development Team, as well as Steve VanDevender and
+ Kevin Smolkowski, ensured that NetHack 3.6 continued to operate on
+ various UNIX flavors and maintained the X11 interface.
- If NetHack is compiled with the SYSCF option, a system ad-
- ministrator should set up a global configuration; this is a file
- in the same format as the traditional per-user configuration file
- (see above). This file should be named sysconf and placed in the
- same directory as the other NetHack support files. The options
- recognized in this file are listed below. Any option not set us-
- es a compiled-in default (which may not be appropriate for your
- system).
+ Ken Lorber, Haoyang Wang, Pat Rankin, and Dean Luick maintained
+ the port of NetHack 3.6 for Mac OSX.
- WIZARDS = A space-separated list of user names who are allowed
- to play in debug mode (commonly referred to as wizard mode). A
- value of a single asterisk (*) allows anyone to start a game in
- debug mode.
+ Michael Allison, David Cohrs, Bart House, Pasi Kallinen, Alex
+ Kompel, Dion Nicolaas, Derek S. Ray and Yitzhak Sapir maintained the
+ port of NetHack 3.6 for Microsoft Windows.
- SHELLERS = A list of users who are allowed to use the shell es-
- cape command (!). The syntax is the same as WIZARDS.
+ Pat Rankin attempted to keep the VMS port running for NetHack
+ 3.6, hindered by limited access. Kevin Smolkowski has updated and
+ tested it for the most recent version of OpenVMS (V8.4 as of this
+ writing) on Alpha and Integrity (aka Itanium aka IA64) but not VAX.
- EXPLORERS = A list of users who are allowed to use the explore
- mode. The syntax is the same as WIZARDS.
- MAXPLAYERS = Limit the maximum number of games that can be run-
- ning at the same time.
- SUPPORT = A string explaining how to get local support (no de-
- fault value).
+ NetHack 3.6.7 February 3, 2023
- RECOVER = A string explaining how to recover a game on this
- system (no default value).
- SEDUCE = 0 or 1 to disable or enable, respectively, the SEDUCE
- option. When disabled, incubi and succubi behave like nymphs.
- CHECK_PLNAME = Setting this to 1 will make the EXPLORERS, WIZ-
- ARDS, and SHELLERS check for the player name instead of the us-
- er's login name.
- CHECK_SAVE_UID = 0 or 1 to disable or enable, respectively, the
- UID (used identification number) checking for save files (to
- verify that the user who is restoring is the same one who
- saved).
- The following options affect the score file:
+ NetHack Guidebook 90
- PERSMAX = Maximum number of entries for one person.
- ENTRYMAX = Maximum number of entries in the score file.
- POINTSMIN = Minimum number of points to get an entry in the
- score file.
+ Ray Chason resurrected the msdos port for 3.6 and contributed the
+ necessary updates to the community at large.
- PERS_IS_UID = 0 or 1 to use user names or numeric userids, re-
- spectively, to identify unique people for the score file.
+ In late April 2018, several hundred bug fixes for 3.6.0 and some
+ new features were assembled and released as NetHack 3.6.1. The
+ NetHack Development Team at the time of release of 3.6.1 consisted of
+ Warwick Allison, Michael Allison, Ken Arromdee, David Cohrs, Jessie
+ Collet, Pasi Kallinen, Ken Lorber, Dean Luick, Patric Mueller, Pat
+ Rankin, Derek S. Ray, Alex Smith, Mike Stephenson, Janet Walz, and
+ Paul Winner.
+ In early May 2019, another 320 bug fixes along with some enhance-
+ ments and the adopted curses window port, were released as 3.6.2.
- NetHack 3.6 March 4, 2020
+ Bart House, who had contributed to the game as a porting team
+ participant for decades, joined the NetHack Development Team in late
+ May 2019.
+ NetHack 3.6.3 was released on December 5, 2019 containing over
+ 190 bug fixes to NetHack 3.6.2.
+ NetHack 3.6.4 was released on December 18, 2019 containing a
+ security fix and a few bug fixes.
+ NetHack 3.6.5 was released on January 27, 2020 containing some
+ security fixes and a small number of bug fixes.
+ NetHack 3.6.6 was released on March 8, 2020 containing a security
+ fix and some bug fixes.
- NetHack Guidebook 86
+ NetHack 3.6.7 was released in February 2023 containing a security
+ fix and some bug fixes.
+ The official NetHack web site is maintained by Ken Lorber at
+ https://www.nethack.org/.
+ 12.1. Special Thanks
- MAX_STATUENAME_RANK = Maximum number of score file entries to
- use for random statue names (default is 10).
+ On behalf of the NetHack community, thank you very much once
+ again to M. Drew Streib and Pasi Kallinen for providing a public
+ NetHack server at nethack.alt.org. Thanks to Keith Simpson and Andy
+ Thomson for hardfought.org. Thanks to all those unnamed dungeoneers
+ who invest their time and effort into annual NetHack tournaments such
+ as Junethack, The November NetHack Tournament, and in days past,
+ devnull.net (gone for now, but not forgotten).
- ACCESSIBILITY = 0 or 1 to disable or enable, respectively, the
- ability for players to set S_pet_override and S_hero_override
- symbols in their configuration file.
- PORTABLE_DEVICE_PATHS = 0 or 1 Windows OS only, the game will
- look for all of its external files, and write to all of its
- output files in one place rather than at the standard loca-
- tions.
- DUMPLOGFILE = A filename where the end-of-game dumplog is
- saved. Not defining this will prevent dumplog from being cre-
- ated. Only available if your game is compiled with DUMPLOG. Al-
- lows the following placeholders:
- %% - literal `%'
- %v - version (eg. "3.6.3-0")
- %u - game UID
- %t - game start time, UNIX timestamp format
- %T - current time, UNIX timestamp format
- %d - game start time, YYYYMMDDhhmmss format
- %D - current time, YYYYMMDDhhmmss format
- %n - player name
- %N - first character of player name
- 10. Scoring
- NetHack maintains a list of the top scores or scorers on
- your machine, depending on how it is set up. In the latter case,
- each account on the machine can post only one non-winning score
- on this list. If you score higher than someone else on this
- list, or better your previous score, you will be inserted in the
- proper place under your current name. How many scores are kept
- can also be set up when NetHack is compiled.
- Your score is chiefly based upon how much experience you
- gained, how much loot you accumulated, how deep you explored, and
- how the game ended. If you quit the game, you escape with all of
- your gold intact. If, however, you get killed in the Mazes of
- Menace, the guild will only hear about 90% of your gold when your
- corpse is discovered (adventurers have been known to collect
- finder's fees). So, consider whether you want to take one last
- hit at that monster and possibly live, or quit and stop with
- whatever you have. If you quit, you keep all your gold, but if
- you swing and live, you might find more.
- If you just want to see what the current top players/games
- list is, you can type nethack -s all on most versions.
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 91
- NetHack Guidebook 87
+ 12.2. Dungeoneers
+ From time to time, some depraved individual out there in netland
+ sends a particularly intriguing modification to help out with the
+ game. The NetHack Development Team sometimes makes note of the names
+ of the worst of these miscreants in this, the list of Dungeoneers:
- 11. Explore mode
- NetHack is an intricate and difficult game. Novices might
- falter in fear, aware of their ignorance of the means to survive.
- Well, fear not. Your dungeon comes equipped with an "explore" or
- "discovery" mode that enables you to keep old save files and
- cheat death, at the paltry cost of not getting on the high score
- list.
- There are two ways of enabling explore mode. One is to
- start the game with the -X command-line switch or with the play-
- mode:explore option. The other is to issue the "#exploremode"
- extended command while already playing the game. Starting a new
- game in explore mode provides your character with a wand of wish-
- ing in initial inventory; switching during play does not. The
- other benefits of explore mode are left for the trepid reader to
- discover.
- 11.1. Debug mode
- Debug mode, also known as wizard mode, is undocumented aside
- from this brief description and the various "debug mode only"
- commands listed among the command descriptions. It is intended
- for tracking down problems within the program rather than to pro-
- vide god-like powers to your character, and players who attempt
- debugging are expected to figure out how to use it themselves.
- It is initiated by starting the game with the -D command-line
- switch or with the playmode:debug option.
- For some systems, the player must be logged in under a par-
- ticular user name to be allowed to use debug mode; for others,
- the hero must be given a particular character name (but may be
- any role; there's no connection between "wizard mode" and the
- Wizard role). Attempting to start a game in debug mode when not
- allowed or not available will result in falling back to explore
- mode instead.
- 12. Credits
- The original hack game was modeled on the Berkeley UNIX
- rogue game. Large portions of this paper were shamelessly
- cribbed from A Guide to the Dungeons of Doom, by Michael C. Toy
- and Kenneth C. R. C. Arnold. Small portions were adapted from
- Further Exploration of the Dungeons of Doom, by Ken Arromdee.
- NetHack is the product of literally dozens of people's work.
- Main events in the course of the game development are described
- below:
- Jay Fenlason wrote the original Hack, with help from Kenny
- Woodland, Mike Thome and Jon Payne.
- Andries Brouwer did a major re-write, transforming Hack into
- a very different game, and published (at least) three versions
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 88
- (1.0.1, 1.0.2, and 1.0.3) for UNIX machines to the Usenet.
- Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS,
- producing PC HACK 1.01e, added support for DEC Rainbow graphics
- in version 1.03g, and went on to produce at least four more ver-
- sions (3.0, 3.2, 3.51, and 3.6).
- R. Black ported PC HACK 3.51 to Lattice C and the Atari
- 520/1040ST, producing ST Hack 1.03.
- Mike Stephenson merged these various versions back together,
- incorporating many of the added features, and produced NetHack
- 1.4. He then coordinated a cast of thousands in enhancing and
- debugging NetHack 1.4 and released NetHack versions 2.2 and 2.3.
- Later, Mike coordinated a major rewrite of the game, heading
- a team which included Ken Arromdee, Jean-Christophe Collet, Steve
- Creps, Eric Hendrickson, Izchak Miller, John Rupley, Mike Threep-
- oint, and Janet Walz, to produce NetHack 3.0c.
- NetHack 3.0 was ported to the Atari by Eric R. Smith, to
- OS/2 by Timo Hakulinen, and to VMS by David Gentzel. The three
- of them and Kevin Darcy later joined the main NetHack Development
- Team to produce subsequent revisions of 3.0.
- Olaf Seibert ported NetHack 2.3 and 3.0 to the Amiga. Norm
- Meluch, Stephen Spackman and Pierre Martineau designed overlay
- code for PC NetHack 3.0. Johnny Lee ported NetHack 3.0 to the
- Macintosh. Along with various other Dungeoneers, they continued
- to enhance the PC, Macintosh, and Amiga ports through the later
- revisions of 3.0.
- Headed by Mike Stephenson and coordinated by Izchak Miller
- and Janet Walz, the NetHack Development Team which now included
- Ken Arromdee, David Cohrs, Jean-Christophe Collet, Kevin Darcy,
- Matt Day, Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin,
- Eric Raymond, and Eric Smith undertook a radical revision of 3.0.
- They re-structured the game's design, and re-wrote major parts of
- the code. They added multiple dungeons, a new display, special
- individual character quests, a new endgame and many other new
- features, and produced NetHack 3.1.
- Ken Lorber, Gregg Wonderly and Greg Olson, with help from
- Richard Addison, Mike Passaretti, and Olaf Seibert, developed
- NetHack 3.1 for the Amiga.
- Norm Meluch and Kevin Smolkowski, with help from Carl Sche-
- lin, Stephen Spackman, Steve VanDevender, and Paul Winner, ported
- NetHack 3.1 to the PC.
- Jon W{tte and Hao-yang Wang, with help from Ross Brown, Mike
- Engber, David Hairston, Michael Hamel, Jonathan Handler, Johnny
- Lee, Tim Lennan, Rob Menke, and Andy Swanson, developed NetHack
- 3.1 for the Macintosh, porting it for MPW. Building on their
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 89
+ Adam Aronow J. Ali Harlow Mikko Juola
+ Alex Kompel Janet Walz Nathan Eady
+ Alex Smith Janne Salmijarvi Norm Meluch
+ Andreas Dorn Jean-Christophe Collet Olaf Seibert
+ Andy Church Jeff Bailey Pasi Kallinen
+ Andy Swanson Jochen Erwied Pat Rankin
+ Andy Thomson John Kallen Patric Mueller
- development, Bart House added a Think C port.
- Timo Hakulinen ported NetHack 3.1 to OS/2. Eric Smith port-
- ed NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua
- Delahunty, was responsible for the VMS version of NetHack 3.1.
- Michael Allison ported NetHack 3.1 to Windows NT.
+ NetHack 3.6.7 February 3, 2023
- Dean Luick, with help from David Cohrs, developed NetHack
- 3.1 for X11. Warwick Allison wrote a tiled version of NetHack
- for the Atari; he later contributed the tiles to the NetHack De-
- velopment Team and tile support was then added to other plat-
- forms.
- The 3.2 NetHack Development Team, comprised of Michael Alli-
- son, Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin
- Darcy, Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Er-
- ic Smith, Mike Stephenson, Janet Walz, and Paul Winner, released
- version 3.2 in April of 1996.
- Version 3.2 marked the tenth anniversary of the formation of
- the development team. In a testament to their dedication to the
- game, all thirteen members of the original NetHack Development
- Team remained on the team at the start of work on that release.
- During the interval between the release of 3.1.3 and 3.2, one of
- the founding members of the NetHack Development Team, Dr. Izchak
- Miller, was diagnosed with cancer and passed away. That release
- of the game was dedicated to him by the development and porting
- teams.
- During the lifespan of NetHack 3.1 and 3.2, several enthusi-
- asts of the game added their own modifications to the game and
- made these "variants" publicly available:
- Tom Proudfoot and Yuval Oren created NetHack++, which was
- quickly renamed NetHack--. Working independently, Stephen White
- wrote NetHack Plus. Tom Proudfoot later merged NetHack Plus and
- his own NetHack-- to produce SLASH. Larry Stewart-Zerba and War-
- wick Allison improved the spell casting system with the Wizard
- Patch. Warwick Allison also ported NetHack to use the Qt inter-
- face.
+ NetHack Guidebook 92
- Warren Cheung combined SLASH with the Wizard Patch to pro-
- duce Slash'EM, and with the help of Kevin Hugo, added more fea-
- tures. Kevin later joined the NetHack Development Team and in-
- corporated the best of these ideas in NetHack 3.3.
- The final update to 3.2 was the bug fix release 3.2.3, which
- was released simultaneously with 3.3.0 in December 1999 just in
- time for the Year 2000.
- The 3.3 NetHack Development Team, consisting of Michael Al-
- lison, Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps,
- Kevin Darcy, Timo Hakulinen, Kevin Hugo, Steve Linhart, Ken Lor-
- ber, Dean Luick, Pat Rankin, Eric Smith, Mike Stephenson, Janet
+ Ari Huttunen John Rupley Paul Winner
+ Bart House John S. Bien Pierre Martineau
+ Benson I. Margulies Johnny Lee Ralf Brown
+ Bill Dyer Jon W{tte Ray Chason
+ Boudewijn Waijers Jonathan Handler Richard Addison
+ Bruce Cox Joshua Delahunty Richard Beigel
+ Bruce Holloway Karl Garrison Richard P. Hughey
+ Bruce Mewborne Keizo Yamamoto Rob Menke
+ Carl Schelin Keith Simpson Robin Bandy
+ Chris Russo Ken Arnold Robin Johnson
+ David Cohrs Ken Arromdee Roderick Schertler
+ David Damerell Ken Lorber Roland McGrath
+ David Gentzel Ken Washikita Ron Van Iwaarden
+ David Hairston Kevin Darcy Ronnen Miller
+ Dean Luick Kevin Hugo Ross Brown
+ Del Lamb Kevin Sitze Sascha Wostmann
+ Derek S. Ray Kevin Smolkowski Scott Bigham
+ Deron Meranda Kevin Sweet Scott R. Turner
+ Dion Nicolaas Lars Huttar Sean Hunt
+ Dylan O'Donnell Leon Arnott Stephen Spackman
+ Eric Backus M. Drew Streib Stefan Thielscher
+ Eric Hendrickson Malcolm Ryan Stephen White
+ Eric R. Smith Mark Gooderum Steve Creps
+ Eric S. Raymond Mark Modrall Steve Linhart
+ Erik Andersen Marvin Bressler Steve VanDevender
+ Fredrik Ljungdahl Matthew Day Teemu Suikki
+ Frederick Roeber Merlyn LeRoy Tim Lennan
+ Gil Neiger Michael Allison Timo Hakulinen
+ Greg Laskin Michael Feir Tom Almy
+ Greg Olson Michael Hamel Tom West
+ Gregg Wonderly Michael Sokolov Warren Cheung
+ Hao-yang Wang Mike Engber Warwick Allison
+ Helge Hafting Mike Gallop Yitzhak Sapir
+ Irina Rempt-Drijfhout Mike Passaretti
+ Izchak Miller Mike Stephenson
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 90
- Walz, and Paul Winner, released 3.3.0 in December 1999 and 3.3.1
- in August of 2000.
- Version 3.3 offered many firsts. It was the first version to
- separate race and profession. The Elf class was removed in pref-
- erence to an elf race, and the races of dwarves, gnomes, and orcs
- made their first appearance in the game alongside the familiar
- human race. Monk and Ranger roles joined Archeologists, Barbar-
- ians, Cavemen, Healers, Knights, Priests, Rogues, Samurai,
- Tourists, Valkyries and of course, Wizards. It was also the
- first version to allow you to ride a steed, and was the first
- version to have a publicly available web-site listing all the
- bugs that had been discovered. Despite that constantly growing
- bug list, 3.3 proved stable enough to last for more than a year
- and a half.
- The 3.4 NetHack Development Team initially consisted of
- Michael Allison, Ken Arromdee, David Cohrs, Jessie Collet, Kevin
- Hugo, Ken Lorber, Dean Luick, Pat Rankin, Mike Stephenson, Janet
- Walz, and Paul Winner, with Warwick Allison joining just before
- the release of NetHack 3.4.0 in March 2002.
- As with version 3.3, various people contributed to the game
- as a whole as well as supporting ports on the different platforms
- that NetHack runs on:
- Pat Rankin maintained 3.4 for VMS.
- Michael Allison maintained NetHack 3.4 for the MS-DOS plat-
- form. Paul Winner and Yitzhak Sapir provided encouragement.
- Dean Luick, Mark Modrall, and Kevin Hugo maintained and en-
- hanced the Macintosh port of 3.4.
- Michael Allison, David Cohrs, Alex Kompel, Dion Nicolaas,
- and Yitzhak Sapir maintained and enhanced 3.4 for the Microsoft
- Windows platform. Alex Kompel contributed a new graphical inter-
- face for the Windows port. Alex Kompel also contributed a Win-
- dows CE port for 3.4.1.
- Ron Van Iwaarden was the sole maintainer of NetHack for OS/2
- the past several releases. Unfortunately Ron's last OS/2 machine
- stopped working in early 2006. A great many thanks to Ron for
- keeping NetHack alive on OS/2 all these years.
- Janne Salmijarvi and Teemu Suikki maintained and enhanced
- the Amiga port of 3.4 after Janne Salmijarvi resurrected it for
- 3.3.1.
- Christian "Marvin" Bressler maintained 3.4 for the Atari af-
- ter he resurrected it for 3.3.1.
- The release of NetHack 3.4.3 in December 2003 marked the be-
- ginning of a long release hiatus. 3.4.3 proved to be a remarkably
+ NetHack 3.6.7 February 3, 2023
- NetHack 3.6 March 4, 2020
+ NetHack Guidebook 93
- NetHack Guidebook 91
+ Brand and product names are trademarks or registered trademarks
+ of their respective holders.
- stable version that provided continued enjoyment by the community
- for more than a decade. The NetHack Development Team slowly and
- quietly continued to work on the game behind the scenes during
- the tenure of 3.4.3. It was during that same period that several
- new variants emerged within the NetHack community. Notably
- sporkhack by Derek S. Ray, unnethack by Patric Mueller, nitrohack
- and its successors originally by Daniel Thaler and then by Alex
- Smith, and Dynahack by Tung Nguyen. Some of those variants con-
- tinue to be developed, maintained, and enjoyed by the community
- to this day.
- In September 2014, an interim snapshot of the code under de-
- velopment was released publicly by other parties. Since that code
- was a work-in-progress and had not gone through the process of
- debugging it as a suitable release, it was decided that the ver-
- sion numbers present on that code snapshot would be retired and
- never used in an official NetHack release. An announcement was
- posted on the NetHack Development Team's official nethack.org
- website to that effect, stating that there would never be a
- 3.4.4, 3.5, or 3.5.0 official release version.
- In January 2015, preparation began for the release of
- NetHack 3.6.
- At the beginning of development for what would eventually
- get released as 3.6.0, the NetHack Development Team consisted of
- Warwick Allison, Michael Allison, Ken Arromdee, David Cohrs,
- Jessie Collet, Ken Lorber, Dean Luick, Pat Rankin, Mike Stephen-
- son, Janet Walz, and Paul Winner. In early 2015, ahead of the
- release of 3.6.0, new members Sean Hunt, Pasi Kallinen, and Derek
- S. Ray joined the NetHack Development Team.
- Near the end of the development of 3.6.0, one of the signif-
- icant inspirations for many of the humorous and fun features
- found in the game, author Terry Pratchett, passed away. NetHack
- 3.6.0 introduced a tribute to him.
- 3.6.0 was released in December 2015, and merged work done by
- the development team since the release of 3.4.3 with some of the
- beloved community patches. Many bugs were fixed and some code was
- restructured.
- The NetHack Development Team, as well as Steve VanDevender
- and Kevin Smolkowski, ensured that NetHack 3.6 continued to oper-
- ate on various UNIX flavors and maintained the X11 interface.
- Ken Lorber, Haoyang Wang, Pat Rankin, and Dean Luick main-
- tained the port of NetHack 3.6 for Mac OSX.
- Michael Allison, David Cohrs, Bart House, Pasi Kallinen,
- Alex Kompel, Dion Nicolaas, Derek S. Ray and Yitzhak Sapir main-
- tained the port of NetHack 3.6 for Microsoft Windows.
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 92
- Pat Rankin attempted to keep the VMS port running for
- NetHack 3.6, hindered by limited access. Kevin Smolkowski has up-
- dated and tested it for the most recent version of OpenVMS (V8.4
- as of this writing) on Alpha and Integrity (aka Itanium aka IA64)
- but not VAX.
- Ray Chason resurrected the msdos port for 3.6 and contrib-
- uted the necessary updates to the community at large.
- In late April 2018, several hundred bug fixes for 3.6.0 and
- some new features were assembled and released as NetHack 3.6.1.
- The NetHack Development Team at the time of release of 3.6.1 con-
- sisted of Warwick Allison, Michael Allison, Ken Arromdee, David
- Cohrs, Jessie Collet, Pasi Kallinen, Ken Lorber, Dean Luick,
- Patric Mueller, Pat Rankin, Derek S. Ray, Alex Smith, Mike
- Stephenson, Janet Walz, and Paul Winner.
- In early May 2019, another 320 bug fixes along with some en-
- hancements and the adopted curses window port, were released as
- 3.6.2.
- Bart House, who had contributed to the game as a porting
- team participant for decades, joined the NetHack Development Team
- in late May 2019.
- NetHack 3.6.3 was released on December 5, 2019 containing
- over 190 bug fixes to NetHack 3.6.2.
- NetHack 3.6.4 was released on December 18, 2019 containing a
- security fix and a few bug fixes.
- NetHack 3.6.5 was released on January 27, 2020 containing
- some security fixes and a small number of bug fixes.
- NetHack 3.6.6 was released in March 2020 containing a secu-
- rity fix.
- The official NetHack web site is maintained by Ken Lorber at
- https://www.nethack.org/.
- 12.1. SPECIAL THANKS
- On behalf of the NetHack community, thank you very much once
- again to M. Drew Streib and Pasi Kallinen for providing a public
- NetHack server at nethack.alt.org. Thanks to Keith Simpson and
- Andy Thomson for hardfought.org. Thanks to all those unnamed dun-
- geoneers who invest their time and effort into annual NetHack
- tournaments such as Junethack, The November NetHack Tournament
- and in days past, devnull.net (gone for now, but not forgotten).
- - - - - - - - - - -
- From time to time, some depraved individual out there in
- netland sends a particularly intriguing modification to help out
- NetHack 3.6 March 4, 2020
- NetHack Guidebook 93
- with the game. The NetHack Development Team sometimes makes note
- of the names of the worst of these miscreants in this, the list
- of Dungeoneers:
- Adam Aronow J. Ali Harlow Mikko Juola
- Alex Kompel Janet Walz Nathan Eady
- Alex Smith Janne Salmijarvi Norm Meluch
- Andreas Dorn Jean-Christophe Collet Olaf Seibert
- Andy Church Jeff Bailey Pasi Kallinen
- Andy Swanson Jochen Erwied Pat Rankin
- Andy Thomson John Kallen Patric Mueller
- Ari Huttunen John Rupley Paul Winner
- Bart House John S. Bien Pierre Martineau
- Benson I. Margulies Johnny Lee Ralf Brown
- Bill Dyer Jon W{tte Ray Chason
- Boudewijn Waijers Jonathan Handler Richard Addison
- Bruce Cox Joshua Delahunty Richard Beigel
- Bruce Holloway Karl Garrison Richard P. Hughey
- Bruce Mewborne Keizo Yamamoto Rob Menke
- Carl Schelin Keith Simpson Robin Bandy
- Chris Russo Ken Arnold Robin Johnson
- David Cohrs Ken Arromdee Roderick Schertler
- David Damerell Ken Lorber Roland McGrath
- David Gentzel Ken Washikita Ron Van Iwaarden
- David Hairston Kevin Darcy Ronnen Miller
- Dean Luick Kevin Hugo Ross Brown
- Del Lamb Kevin Sitze Sascha Wostmann
- Derek S. Ray Kevin Smolkowski Scott Bigham
- Deron Meranda Kevin Sweet Scott R. Turner
- Dion Nicolaas Lars Huttar Sean Hunt
- Dylan O'Donnell Leon Arnott Stephen Spackman
- Eric Backus M. Drew Streib Stefan Thielscher
- Eric Hendrickson Malcolm Ryan Stephen White
- Eric R. Smith Mark Gooderum Steve Creps
- Eric S. Raymond Mark Modrall Steve Linhart
- Erik Andersen Marvin Bressler Steve VanDevender
- Fredrik Ljungdahl Matthew Day Teemu Suikki
- Frederick Roeber Merlyn LeRoy Tim Lennan
- Gil Neiger Michael Allison Timo Hakulinen
- Greg Laskin Michael Feir Tom Almy
- Greg Olson Michael Hamel Tom West
- Gregg Wonderly Michael Sokolov Warren Cheung
- Hao-yang Wang Mike Engber Warwick Allison
- Helge Hafting Mike Gallop Yitzhak Sapir
- Irina Rempt-Drijfhout Mike Passaretti
- Izchak Miller Mike Stephenson
- Brand and product names are trademarks or registered trade-
- marks of their respective holders.
@@ -6132,7 +6132,7 @@
- NetHack 3.6 March 4, 2020
+ NetHack 3.6.7 February 3, 2023
diff --git a/doc/config.nh b/doc/config.nh
index 4371582508..fced3d40c9 100644
--- a/doc/config.nh
+++ b/doc/config.nh
@@ -486,7 +486,7 @@
# Show all unholy water in red
#MENUCOLOR=" unholy " = red
# Show all cursed worn items in orange and underlined
-#MENUCOLOR=" cursed .* (being worn)" = orange&underline
+#MENUCOLOR=" cursed .* \(being worn\)" = orange&underline
# Use the IBM character set rather than just plain ascii characters
diff --git a/doc/fixes36.6 b/doc/fixes36.6
index 21ccaaef7d..aaa2b875f8 100644
--- a/doc/fixes36.6
+++ b/doc/fixes36.6
@@ -1,4 +1,4 @@
-$NHDT-Branch: NetHack-3.6-Mar2020 $:$NHDT-Revision: 1.2 $ $NHDT-Date: 1583606861 2020/03/07 18:47:41 $
+$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1587039894 2020/04/16 12:24:54 $
fixes36.6 contains a terse summary of changes made to 3.6.5 in order to
produce 3.6.6 as well as any post-release fixes in binaries.
@@ -17,9 +17,10 @@ avoid "'s glorkum pass harmlessly through the shade" for weaponless mon
Platform- and/or Interface-Specific Fixes or Features
-----------------------------------------------------
+teach unix/Makefile.doc how to make Guidebook.dat, an unpaginated copy of
+ Guidebook.txt
General New Features
--------------------
none
-
diff --git a/doc/fixes36.7 b/doc/fixes36.7
new file mode 100644
index 0000000000..7f14da15f2
--- /dev/null
+++ b/doc/fixes36.7
@@ -0,0 +1,71 @@
+$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
+produce 3.6.7 as well as any post-release fixes in binaries.
+
+
+General Fixes and Modified Features
+-----------------------------------
+during engraving, spaces were counted instead of non-space (cherry-pick of
+ 4e0a1e04 from NetHack-3.7)
+avoid potential buffer overflow in append_str()
+resolve missing dependency in NetHack.sln
+code in include/tradstdc.h was trying to suppress warn_unused result by
+ defining warn_unused_result to an empty string and that began causing
+ a build error within a system-supplied header file cdefs.h when using
+ ubuntu impish 21.10; disable that for any Linux unless GCC_URWARN is
+ defined to force it back into effect
+update_inventory() after leash goes slack
+player assigned name for monsters, specific objects, or object types could be
+ longer than what was intented to be allowed; for 'curses', much longer
+
+Platform- and/or Interface-Specific Fixes or Features
+-----------------------------------------------------
+windows: added winflexbison to travis-ci configuration to permit full build of
+ levcomp and dgncomp
+windows: a bad chdir specified in win/win32/dgnstuff.mak caused full build to
+ abort
+windows: the console.rc file had outdated information stating 3.6.3 when the
+ official 3.6.6 binary was built.
+windows: switch from using keyhandling dll's to incorporating the three
+ variations (default, ray, 340) in sys/winnt/nttty.c
+curses: cherry-picked selectsaved code from 3.7 for menu of save files
+NetHackW: fix delay rendering of cursor when using farlook
+
+
+General New Features
+--------------------
+none
+
+
+Fixes to 3.6.7 Post-release Problems and other Post-release changes
+-------------------------------------------------------------------
+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
diff --git a/doc/makedefs.6 b/doc/makedefs.6
index 79179969f6..cf78b6d90f 100644
--- a/doc/makedefs.6
+++ b/doc/makedefs.6
@@ -125,11 +125,25 @@ file.
.TP
.B -s
Generate the
-.I bogusmon
-,
-.I engrave
-and
-.IR epitaph files.
+.IR bogusmon ", " engrave ", and " epitaph " files."
+.br
+.TP
+.B -1
+Generate the
+.IR epitaph
+file.
+.br
+.TP
+.B -2
+Generate the
+.IR engrave
+file.
+.br
+.TP
+.B -3
+Generate the
+.IR bogusmon
+file.
.br
.TP
.B -h
diff --git a/doc/tmac.nh b/doc/tmac.nh
index 5a1bd0a607..7604f8e4c2 100644
--- a/doc/tmac.nh
+++ b/doc/tmac.nh
@@ -1,4 +1,4 @@
-.\" NetHack 3.6 tmac.nh $NHDT-Date: $ $NHDT-Branch: $:$NHDT-Revision: $
+.\" NetHack 3.6 tmac.nh
.
.\" Miscellaneous tmac.n-style macros specifically for nethack's Guidebook.
.\"
@@ -8,6 +8,10 @@
.\" cluttered as their number increased. It now uses the '.so' directive
.\" to include this file. (tmac.n is passed to 'roff on the command line.)
.
+.\" Protect against being sourced twice.
+.nr nH +1
+.if \n(nH>1 .nx
+.
.\" labeled paragraph start
.\" .PS word
.\" set the width for the label column
@@ -85,7 +89,8 @@
. if \\n(id=0 \{\
. di \" end diversion
. fi \" resume filling
-. in -\\n(piu \" dedent
+. ie \\n(.i<\\n(pi .in 0
+. el .in -\\n(piu \" dedent
. ev \" pop environment
. ne \\n(dnu \" be sure you have room
. nf \" don't reprocess display
@@ -118,7 +123,7 @@
.\" $1 - repeat count for amount of padding (optional; default is 1)
.de BR
.ie \\.$==0 .nr bR 1v
-.el .nr bR (\\$1-0)v
+.el .nr bR 0\\$1v
\0
.sp \\n(bR
.br
@@ -129,4 +134,9 @@
\\$1\\$2
..
.
+.\" groff and AT&T-descended troffs use different hyphenation patterns.
+.\" Don't hyphenate the last word on a page or column, or
+.\" before/after last/first 2 characters of a word.
+.ie \n(.g .hy 12
+.el .hy 14
.\"tmac.nh/"
diff --git a/include/decl.h b/include/decl.h
index c6e298b43b..d550180f12 100644
--- a/include/decl.h
+++ b/include/decl.h
@@ -295,6 +295,9 @@ E NEARDATA struct c_color_names {
#define NH_WHITE c_color_names.c_white
#define NH_ORANGE c_color_names.c_orange
+E boolean deferred_showpaths; /* decl.c */
+E char *deferred_showpaths_dir; /* decl.c */
+
/* The names of the colors used for gems, etc. */
E const char *c_obj_colors[];
diff --git a/include/extern.h b/include/extern.h
index a1b32f76af..023d249016 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -848,10 +848,11 @@ E void NDECL(really_close);
#ifdef DEBUG
E boolean FDECL(debugcore, (const char *, BOOLEAN_P));
#endif
-E void NDECL(reveal_paths);
+E void FDECL(reveal_paths, (int));
E boolean FDECL(read_tribute, (const char *, const char *, int,
char *, int, unsigned));
E boolean FDECL(Death_quote, (char *, int));
+extern void FDECL(do_deferred_showpaths, (int));
/* ### fountain.c ### */
@@ -1680,7 +1681,8 @@ E void FDECL(set_output_mode, (int));
E void NDECL(synch_cursor);
E void NDECL(nethack_enter_nttty);
E void NDECL(nttty_exit);
-#endif
+E int NDECL(set_keyhandling_via_option);
+#endif /* WIN32 */
/* ### o_init.c ### */
@@ -2592,6 +2594,7 @@ E void FDECL(sethanguphandler, (void (*)(int)));
E boolean NDECL(authorize_wizard_mode);
E boolean FDECL(check_user_string, (char *));
E char *NDECL(get_login_name);
+E void after_opt_showpaths(const char *) NORETURN;
#endif /* UNIX */
/* ### unixtty.c ### */
diff --git a/include/flag.h b/include/flag.h
index 3b429e01fb..f10dc9ca26 100644
--- a/include/flag.h
+++ b/include/flag.h
@@ -222,6 +222,15 @@ enum getloc_filters {
NUM_GFILTER
};
+#ifdef WIN32
+enum windows_key_handling {
+ no_keyhandling,
+ default_keyhandling,
+ ray_keyhandling,
+ nh340_keyhandling
+};
+#endif
+
struct debug_flags {
boolean test;
#ifdef TTY_GRAPHICS
@@ -427,8 +436,9 @@ struct instance_flags {
int wc2_windowborders; /* display borders on NetHack windows */
int wc2_petattr; /* text attributes for pet */
#ifdef WIN32
-#define MAX_ALTKEYHANDLER 25
- char altkeyhandler[MAX_ALTKEYHANDLER];
+#define MAX_ALTKEYHANDLING 25
+ char altkeyhandling[MAX_ALTKEYHANDLING];
+ enum windows_key_handling key_handling;
#endif
/* copies of values in struct u, used during detection when the
originals are temporarily cleared; kept here rather than
diff --git a/include/global.h b/include/global.h
index a2b70d2587..5c02491c32 100644
--- a/include/global.h
+++ b/include/global.h
@@ -19,7 +19,7 @@
/*
* Development status of this NetHack version.
*/
-#define NH_DEVEL_STATUS NH_STATUS_RELEASED
+#define NH_DEVEL_STATUS NH_STATUS_POSTRELEASE
#ifndef DEBUG /* allow tool chains to define without causing warnings */
#define DEBUG
diff --git a/include/isaac64.h b/include/isaac64.h
index 6c9b45b524..da9d5a0466 100644
--- a/include/isaac64.h
+++ b/include/isaac64.h
@@ -1,7 +1,7 @@
/* CC0 (Public domain) - see http://creativecommons.org/publicdomain/zero/1.0/ for details */
#if !defined(_isaac64_H)
# define _isaac64_H (1)
-# include
+# include "integer.h"
diff --git a/include/ntconf.h b/include/ntconf.h
index 50b9bf81cd..a3a5b37133 100644
--- a/include/ntconf.h
+++ b/include/ntconf.h
@@ -234,7 +234,7 @@ extern void FDECL(nttty_preference_update, (const char *));
extern void NDECL(toggle_mouse_support);
extern void FDECL(map_subkeyvalue, (char *));
#if defined(WIN32CON)
-extern void FDECL(set_altkeyhandler, (const char *));
+extern void set_altkeyhandling(const char *);
#endif
extern void NDECL(raw_clear_screen);
diff --git a/include/patchlevel.h b/include/patchlevel.h
index 36bc437c6e..722f6eb5f5 100644
--- a/include/patchlevel.h
+++ b/include/patchlevel.h
@@ -1,4 +1,4 @@
-/* NetHack 3.6 patchlevel.h $NHDT-Date: 1583508697 2020/03/06 15:31:37 $ $NHDT-Branch: NetHack-3.6-Mar2020 $:$NHDT-Revision: 1.139 $ */
+/* NetHack 3.6 patchlevel.h $NHDT-Date: 1674867524 2023/01/28 00:58:44 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.141 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -9,14 +9,14 @@
/*
* PATCHLEVEL is updated for each release.
*/
-#define PATCHLEVEL 6
+#define PATCHLEVEL 7
/*
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 0
-#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020"
+#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2025"
#define COPYRIGHT_BANNER_B \
" By Stichting Mathematisch Centrum and M. Stephenson."
/* COPYRIGHT_BANNER_C is generated by makedefs into date.h */
@@ -36,7 +36,34 @@
/****************************************************************************/
/* Version 3.6.x */
+/* Patch 7, February 16, 2023
+ *
+ * during engraving, spaces were counted instead of non-space (cherry-pick of
+ * 4e0a1e04 from NetHack-3.7)
+ * avoid potential buffer overflow in append_str()
+ * resolve missing dependency in NetHack.sln
+ * code in include/tradstdc.h was trying to suppress warn_unused result by
+ * defining warn_unused_result to an empty string and that began causing
+ * a build error within a system-supplied header file cdefs.h when using
+ * ubuntu impish 21.10; disable that for any Linux unless GCC_URWARN is
+ * defined to force it back into effect
+ * update_inventory() after leash goes slack
+ * player assigned name for monsters, specific objects, or object types could be
+ longer than what was intented to be allowed; for 'curses', much longer
+ * windows: added winflexbison to travis-ci configuration to permit full build of
+ * levcomp and dgncomp
+ * windows: a bad chdir specified in win/win32/dgnstuff.mak caused full build to
+ * abort
+ * windows: the console.rc file had outdated information stating 3.6.3 when the
+ * official 3.6.6 binary was built.
+ * windows: switch from using keyhandling dll's to incorporating the three
+ * variations (default, ray, 340) in sys/winnt/nttty.c
+ * curses: cherry-picked selectsaved code from 3.7 for menu of save files
+ * NetHackW: fix delayed rendering of cursor when using farlook
+ */
+
/* Patch 6, March 8, 2020
+ *
* invalid status highlight color could be maliciously used to corrupt memory
* formatting corpse names used internal buffers differently from formatting
* other objects and could potentially clobber memory
diff --git a/include/system.h b/include/system.h
index a2cb51f409..14b15d09b6 100644
--- a/include/system.h
+++ b/include/system.h
@@ -60,9 +60,13 @@ typedef long off_t;
#endif
#ifndef SIG_RET_TYPE
#if defined(NHSTDC) || defined(POSIX_TYPES) || defined(OS2) || defined(__DECC)
+#if defined(LINUX) && defined(__GNUC__)
+#define SIG_RET_TYPE __sighandler_t
+#else
#define SIG_RET_TYPE void (*)()
#endif
#endif
+#endif
#ifndef SIG_RET_TYPE
#if defined(ULTRIX) || defined(SUNOS4) || defined(SVR3) || defined(SVR4)
/* SVR3 is defined automatically by some systems */
@@ -95,8 +99,10 @@ E int FDECL(srandom, (unsigned int));
E long NDECL(lrand48);
E void FDECL(srand48, (long));
#else
+#ifndef LINUX
E long lrand48();
E void srand48();
+#endif
#endif /* MACOSX */
#endif /* BSD || ULTRIX || RANDOM */
@@ -351,6 +357,7 @@ E char *FDECL(memset, (char *, int, int));
#endif /* TOS */
#endif /* MICRO */
+#ifndef LINUX
#if defined(BSD) && defined(ultrix) /* i.e., old versions of Ultrix */
E void sleep();
#endif
@@ -360,6 +367,7 @@ E unsigned sleep();
#if defined(HPUX)
E unsigned int FDECL(sleep, (unsigned int));
#endif
+#endif
#ifdef VMS
E int FDECL(sleep, (unsigned));
#endif
@@ -519,7 +527,11 @@ E char *FDECL(tgoto, (const char *, int, int));
#else
#if !(defined(HPUX) && defined(_POSIX_SOURCE))
E int FDECL(tgetent, (char *, const char *));
+#if !(defined(LINUX) && defined(__GNUC__))
E void FDECL(tputs, (const char *, int, int (*)()));
+#else
+E int tputs(const char *, int, int (*)(int));
+#endif
#endif
E int FDECL(tgetnum, (const char *));
E int FDECL(tgetflag, (const char *));
diff --git a/include/tradstdc.h b/include/tradstdc.h
index 12a0d4afe2..f5fb90c1b0 100644
--- a/include/tradstdc.h
+++ b/include/tradstdc.h
@@ -429,12 +429,14 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
#if __GNUC__ >= 3
#define UNUSED __attribute__((unused))
#define NORETURN __attribute__((noreturn))
+#if (!defined(__linux__) && !defined(__APPLE__)) || defined(GCC_URWARN)
/* disable gcc's __attribute__((__warn_unused_result__)) since explicitly
discarding the result by casting to (void) is not accepted as a 'use' */
#define __warn_unused_result__ /*empty*/
#define warn_unused_result /*empty*/
#endif
#endif
+#endif
#ifndef PRINTF_F
#define PRINTF_F(f, v)
diff --git a/include/winprocs.h b/include/winprocs.h
index 55b2b06113..845669d3f4 100644
--- a/include/winprocs.h
+++ b/include/winprocs.h
@@ -1,4 +1,4 @@
-/* NetHack 3.6 winprocs.h $NHDT-Date: 1567213890 2019/08/31 01:11:30 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.50 $ */
+/* NetHack 3.6 winprocs.h $NHDT-Date: 1683746775 2023/05/10 19:26:15 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.53 $ */
/* Copyright (c) David Cohrs, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -6,6 +6,9 @@
#define WINPROCS_H
#include "botl.h"
+#ifndef CLR_MAX
+#include "color.h"
+#endif
/* NB: this MUST match chain_procs below */
struct window_procs {
diff --git a/src/.gitignore b/src/.gitignore
index 6cdb6269a0..44101d8c02 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -12,4 +12,6 @@ graphicschk
nhdat
o
nhdat*
-
+#address san
+*.exp
+*.lib
diff --git a/src/apply.c b/src/apply.c
index e77984d30f..8c76e16381 100644
--- a/src/apply.c
+++ b/src/apply.c
@@ -572,8 +572,10 @@ boolean feedback;
Your("leash falls slack.");
}
for (otmp = invent; otmp; otmp = otmp->nobj)
- if (otmp->otyp == LEASH && otmp->leashmon == (int) mtmp->m_id)
+ if (otmp->otyp == LEASH && otmp->leashmon == (int) mtmp->m_id) {
otmp->leashmon = 0;
+ update_inventory();
+ }
mtmp->mleashed = 0;
}
diff --git a/src/artifact.c b/src/artifact.c
index 03573fe1d1..9d157c9495 100644
--- a/src/artifact.c
+++ b/src/artifact.c
@@ -6,6 +6,7 @@
#include "hack.h"
#include "artifact.h"
#include "artilist.h"
+#include "assert.h"
/*
* Note: both artilist[] and artiexist[] have a dummy element #0,
@@ -30,6 +31,7 @@ STATIC_DCL uchar FDECL(abil_to_adtyp, (long *));
STATIC_DCL int FDECL(glow_strength, (int));
STATIC_DCL boolean FDECL(untouchable, (struct obj *, BOOLEAN_P));
STATIC_DCL int FDECL(count_surround_traps, (int, int));
+STATIC_DCL void dispose_of_orig_obj(struct obj *);
/* The amount added to the victim's total hit points to insure that the
victim will be killed even after damage bonus/penalty adjustments.
@@ -192,22 +194,45 @@ aligntyp alignment; /* target alignment, or A_NONE */
a = &artilist[m];
/* make an appropriate object if necessary, then christen it */
- if (by_align)
- otmp = mksobj((int) a->otyp, TRUE, FALSE);
+ if (by_align) {
+ struct obj *artiobj = mksobj((int) a->otyp, TRUE, FALSE);
- if (otmp) {
- otmp = oname(otmp, a->name);
- otmp->oartifact = m;
- artiexist[m] = TRUE;
+ /* nonnull value of 'otmp' is unexpected. Cope. */
+ if (otmp) /* just in case; avoid orphaning */
+ dispose_of_orig_obj(otmp);
+ otmp = artiobj;
}
+ /*
+ * otmp should be nonnull at this point:
+ * either the passed argument (if !by_align == A_NONE), or
+ * the result of mksobj() just above if by_align is an alignment. */
+ assert(otmp != 0);
+ /* prevent erosion from generating */
+ otmp->oeroded = otmp->oeroded2 = 0;
+ otmp = oname(otmp, a->name);
+ otmp->oartifact = m; /* probably already set by this point, but */
+ artiexist[m] = 1;
} else {
/* nothing appropriate could be found; return original object */
- if (by_align)
- otmp = 0; /* (there was no original object) */
+ if (by_align && otmp) {
+ /* (there shouldn't have been an original object) */
+ dispose_of_orig_obj(otmp);
+ otmp = 0;
+ }
}
return otmp;
}
+STATIC_OVL void
+dispose_of_orig_obj(struct obj *obj)
+{
+ if (!obj)
+ return;
+
+ obj_extract_self(obj);
+ obfree(obj, (struct obj *) 0);
+}
+
/*
* Returns the full name (with articles and correct capitalization) of an
* artifact named "name" if one exists, or NULL, it not.
diff --git a/src/bones.c b/src/bones.c
index da0de0f412..3f9ae2f73b 100644
--- a/src/bones.c
+++ b/src/bones.c
@@ -566,9 +566,9 @@ struct obj *corpse;
store_savefileinfo(fd);
bwrite(fd, (genericptr_t) &c, sizeof c);
bwrite(fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
- savefruitchn(fd, WRITE_SAVE | FREE_SAVE);
+ savefruitchn(fd, WRITE_SAVE);
update_mlstmv(); /* update monsters for eventual restoration */
- savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
+ savelev(fd, ledger_no(&u.uz), WRITE_SAVE);
bclose(fd);
commit_bonesfile(&u.uz);
compress_bonesfile();
diff --git a/src/botl.c b/src/botl.c
index 4c7dbf33a1..8908edb4c9 100644
--- a/src/botl.c
+++ b/src/botl.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 botl.c $NHDT-Date: 1573178085 2019/11/08 01:54:45 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.148 $ */
+/* NetHack 3.6 botl.c $NHDT-Date: 1757734870 2025/09/12 19:41:10 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.149 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1970,6 +1970,13 @@ int arrmin, arrmax;
start_menu(tmpwin);
for (i = arrmin; i < arrmax; i++) {
+ /* 3.6.7+: manually cherry-picked from 3.7 commit
+ 4e2494c8595fce30de9a028a6ac0e21197c30972;
+ when interactively setting a text match highlight
+ for hunger, skip Null placeholder for "not hungry" */
+ if (!arr[i])
+ continue;
+
any = zeroany;
any.a_int = i + adj;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
diff --git a/src/decl.c b/src/decl.c
index 4ae704d410..a37b259037 100644
--- a/src/decl.c
+++ b/src/decl.c
@@ -300,6 +300,9 @@ const char *fqn_prefix_names[PREFIX_COUNT] = {
};
#endif
+boolean deferred_showpaths = FALSE;
+char *deferred_showpaths_dir = (char *) 0;
+
NEARDATA struct savefile_info sfcap = {
#ifdef NHSTDC
0x00000000UL
diff --git a/src/do_name.c b/src/do_name.c
index f1d8d5bb94..2c3f4e6a2e 100644
--- a/src/do_name.c
+++ b/src/do_name.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 do_name.c $NHDT-Date: 1582364431 2020/02/22 09:40:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.174 $ */
+/* NetHack 3.6 do_name.c $NHDT-Date: 1674864731 2023/01/28 00:12:11 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.154 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -9,6 +9,7 @@ STATIC_DCL char *NDECL(nextmbuf);
STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *));
STATIC_DCL int FDECL(CFDECLSPEC cmp_coord_distu, (const void *, const void *));
STATIC_DCL boolean FDECL(gather_locs_interesting, (int, int, int));
+STATIC_DCL char *FDECL(name_from_player, (char *, const char *, const char *));
STATIC_DCL void FDECL(gather_locs, (coord **, int *, int));
STATIC_DCL int FDECL(gloc_filter_floodfill_matcharea, (int, int));
STATIC_DCL void FDECL(auto_describe, (int, int));
@@ -1061,6 +1062,34 @@ struct obj *obj;
return "";
}
+/* get a name for a monster or an object from player;
+ truncate if longer than PL_PSIZ, then return it */
+static char *
+name_from_player(outbuf, prompt, defres)
+char *outbuf; /* output buffer, assumed to be at least BUFSZ long;
+ * anything longer than PL_PSIZ will be truncated */
+const char *prompt;
+const char *defres; /* only used if EDIT_GETLIN is enabled; only useful
+ * if windowport xxx's xxx_getlin() supports that */
+{
+ outbuf[0] = '\0';
+#ifdef EDIT_GETLIN
+ if (defres && *defres)
+ Strcpy(outbuf, defres); /* default response from getlin() */
+#else
+ nhUse(defres);
+#endif
+ getlin(prompt, outbuf);
+ if (!*outbuf || *outbuf == '\033')
+ return NULL;
+
+ /* strip leading and trailing spaces, condense internal sequences */
+ (void) mungspaces(outbuf);
+ if (strlen(outbuf) >= PL_PSIZ)
+ outbuf[PL_PSIZ - 1] = '\0';
+ return outbuf;
+}
+
/* historical note: this returns a monster pointer because it used to
allocate a new bigger block of memory to hold the monster and its name */
struct monst *
@@ -1158,17 +1187,9 @@ do_mname()
/* special case similar to the one in lookat() */
Sprintf(qbuf, "What do you want to call %s?",
distant_monnam(mtmp, ARTICLE_THE, monnambuf));
- buf[0] = '\0';
-#ifdef EDIT_GETLIN
- /* if there's an existing name, make it be the default answer */
- if (has_mname(mtmp))
- Strcpy(buf, MNAME(mtmp));
-#endif
- getlin(qbuf, buf);
- if (!*buf || *buf == '\033')
+ /* use getlin() to get a name string from the player */
+ if (!name_from_player(buf, qbuf, has_mname(mtmp) ? MNAME(mtmp) : NULL))
return;
- /* strip leading and trailing spaces; unnames monster if all spaces */
- (void) mungspaces(buf);
/* Unique monsters have their own specific names or titles.
* Shopkeepers, temple priests and other minions use alternate
@@ -1220,17 +1241,9 @@ register struct obj *obj;
Sprintf(qbuf, "What do you want to name %s ",
is_plural(obj) ? "these" : "this");
(void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
- buf[0] = '\0';
-#ifdef EDIT_GETLIN
- /* if there's an existing name, make it be the default answer */
- if (has_oname(obj))
- Strcpy(buf, ONAME(obj));
-#endif
- getlin(qbuf, buf);
- if (!*buf || *buf == '\033')
+ /* use getlin() to get a name string from the player */
+ if (!name_from_player(buf, qbuf, safe_oname(obj)))
return;
- /* strip leading and trailing spaces; unnames item if all spaces */
- (void) mungspaces(buf);
/*
* We don't violate illiteracy conduct here, although it is
@@ -1484,14 +1497,8 @@ struct obj *obj;
docall_xname, simpleonames, "thing");
/* pointer to old name */
str1 = &(objects[obj->otyp].oc_uname);
- buf[0] = '\0';
-#ifdef EDIT_GETLIN
- /* if there's an existing name, make it be the default answer */
- if (*str1)
- Strcpy(buf, *str1);
-#endif
- getlin(qbuf, buf);
- if (!*buf || *buf == '\033')
+ /* use getlin() to get a name string from the player */
+ if (!name_from_player(buf, qbuf, *str1))
return;
/* clear old name */
diff --git a/src/engrave.c b/src/engrave.c
index b0018556f5..d60fd6f1e7 100644
--- a/src/engrave.c
+++ b/src/engrave.c
@@ -1139,7 +1139,7 @@ doengrave()
/* Chop engraving down to size if necessary */
if (len > maxelen) {
for (sp = ebuf; maxelen && *sp; sp++)
- if (*sp == ' ')
+ if (!(*sp == ' '))
maxelen--;
if (!maxelen && *sp) {
*sp = '\0';
diff --git a/src/files.c b/src/files.c
index 44413f2300..e0395bddd9 100644
--- a/src/files.c
+++ b/src/files.c
@@ -3935,6 +3935,8 @@ assure_syscf_file()
close(fd);
return;
}
+ if (deferred_showpaths)
+ do_deferred_showpaths(1); /* does not return */
raw_printf("Unable to open SYSCF_FILE.\n");
exit(EXIT_FAILURE);
}
@@ -3942,6 +3944,29 @@ assure_syscf_file()
#endif /* SYSCF_FILE */
#endif /* SYSCF */
+void
+do_deferred_showpaths(code)
+int code;
+{
+ deferred_showpaths = FALSE;
+ reveal_paths(code);
+
+#ifdef UNIX
+ after_opt_showpaths(deferred_showpaths_dir);
+#else
+#if !defined(WIN32)
+#ifdef CHDIR
+ chdirx(deferred_showpaths_dir, 0);
+#endif
+#endif
+#if defined(WIN32) || defined(MICRO) || defined(OS2)
+ nethack_exit(EXIT_SUCCESS);
+#else
+ exit(EXIT_SUCCESS);
+#endif
+#endif
+}
+
#ifdef DEBUG
/* used by debugpline() to decide whether to issue a message
* from a particular source file; caller passes __FILE__ and we check
@@ -4022,10 +4047,15 @@ boolean wildcards;
#endif
#endif
+#define SYSCONFFILE "system configuration file"
+
void
-reveal_paths(VOID_ARGS)
+reveal_paths(code)
+int code;
{
+ boolean skip_sysopt = FALSE;
const char *fqn, *nodumpreason;
+
char buf[BUFSZ];
#if defined(SYSCF) || !defined(UNIX) || defined(DLB)
const char *filep;
@@ -4057,7 +4087,8 @@ reveal_paths(VOID_ARGS)
#else
buf[0] = '\0';
#endif
- raw_printf("%s system configuration file%s:", s_suffix(gamename), buf);
+ raw_printf("%s %s%s:", s_suffix(gamename),
+ SYSCONFFILE, buf);
#ifdef SYSCF_FILE
filep = SYSCF_FILE;
#else
@@ -4069,6 +4100,11 @@ reveal_paths(VOID_ARGS)
filep = configfile;
}
raw_printf(" \"%s\"", filep);
+ if (code == 1) {
+ raw_printf("NOTE: The %s above is missing or inaccessible!",
+ SYSCONFFILE);
+ skip_sysopt = TRUE;
+ }
#else /* !SYSCF */
raw_printf("No system configuration file.");
#endif /* ?SYSCF */
@@ -4141,17 +4177,22 @@ reveal_paths(VOID_ARGS)
/* dumplog */
+ fqn = (char *) 0;
#ifndef DUMPLOG
nodumpreason = "not supported";
#else
nodumpreason = "disabled";
#ifdef SYSCF
- fqn = sysopt.dumplogfile;
+ if (!skip_sysopt) {
+ fqn = sysopt.dumplogfile;
+ if (!fqn)
+ nodumpreason = "DUMPLOGFILE is not set in " SYSCONFFILE;
+ } else {
+ nodumpreason = SYSCONFFILE " is missing; no DUMPLOGFILE setting";
+ }
#else /* !SYSCF */
#ifdef DUMPLOG_FILE
fqn = DUMPLOG_FILE;
-#else
- fqn = (char *) 0;
#endif
#endif /* ?SYSCF */
if (fqn && *fqn) {
@@ -4159,16 +4200,24 @@ reveal_paths(VOID_ARGS)
(void) dump_fmtstr(fqn, buf, FALSE);
buf[sizeof buf - sizeof " \"\""] = '\0';
raw_printf(" \"%s\"", buf);
- } else
-#endif /* ?DUMPLOG */
+ } else {
raw_printf("No end-of-game disclosure file (%s).", nodumpreason);
+ }
+#endif /* ?DUMPLOG */
#ifdef WIN32
- if (sysopt.portable_device_paths) {
- const char *pd = get_portable_device();
-
- raw_printf("portable_device_paths (set in sysconf):");
- raw_printf(" \"%s\"", pd);
+ if (!skip_sysopt) {
+ if (sysopt.portable_device_paths) {
+ const char *pd = get_portable_device();
+
+ /* an empty value for pd indicates that portable_device_paths
+ got set TRUE in a sysconf file other than the one containing
+ the executable; disregard it */
+ if (strlen(pd) > 0) {
+ raw_printf("portable_device_paths (set in sysconf):");
+ raw_printf(" \"%s\"", pd);
+ }
+ }
}
#endif
diff --git a/src/fountain.c b/src/fountain.c
index 57e914559f..30051ca994 100644
--- a/src/fountain.c
+++ b/src/fountain.c
@@ -294,14 +294,16 @@ drinkfountain()
dowaterdemon();
break;
case 24: /* Curse an item */ {
- register struct obj *obj;
+ register struct obj *obj, *nextobj;
pline("This water's no good!");
morehungry(rn1(20, 11));
exercise(A_CON, FALSE);
- for (obj = invent; obj; obj = obj->nobj)
+ for (obj = invent; obj; obj = nextobj) {
+ nextobj = obj->nobj;
if (!rn2(5))
curse(obj);
+ }
break;
}
case 25: /* See invisible */
diff --git a/src/invent.c b/src/invent.c
index 7e7e3b2182..51075ccbdc 100644
--- a/src/invent.c
+++ b/src/invent.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 invent.c $NHDT-Date: 1575245062 2019/12/02 00:04:22 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.267 $ */
+/* NetHack 3.6 invent.c $NHDT-Date: 1674864733 2023/01/28 00:12:13 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.268 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1178,7 +1178,8 @@ void
delobj(obj)
register struct obj *obj;
{
- boolean update_map;
+ boolean update_map, was_pile, is_pile;
+ int x = 0, y = 0;
if (obj->otyp == AMULET_OF_YENDOR
|| obj->otyp == CANDELABRUM_OF_INVOCATION
@@ -1192,9 +1193,19 @@ register struct obj *obj;
return;
}
update_map = (obj->where == OBJ_FLOOR);
+ if (update_map) {
+ x = obj->ox;
+ y = obj->oy;
+ was_pile = (level.objects[x][y] && level.objects[x][y]->nexthere);
+ }
obj_extract_self(obj);
- if (update_map)
- newsym(obj->ox, obj->oy);
+ if (update_map) {
+ is_pile = (level.objects[x][y] && level.objects[x][y]->nexthere);
+ if (was_pile != is_pile)
+ newsym_force(x, y);
+ else
+ newsym(x, y);
+ }
obfree(obj, (struct obj *) 0); /* frees contents also */
}
@@ -2462,9 +2473,12 @@ long quan; /* if non-0, print this quantity, not obj->quan */
#else
static char li[BUFSZ];
#endif
+ char suffix[80]; /* plenty of room for count and hallucinatory currency */
+ int sfxlen, txtlen; /* signed int for %*s formatting */
+ const char *fmt;
boolean use_invlet = (flags.invlet_constant
&& let != CONTAINED_SYM && let != HANDS_SYM);
- long savequan = 0;
+ long savequan = 0L;
if (quan && obj) {
savequan = obj->quan;
@@ -2476,18 +2490,33 @@ long quan; /* if non-0, print this quantity, not obj->quan */
* * Then obj == null and we are printing a total amount.
* > Then the object is contained and doesn't have an inventory letter.
*/
- if (cost != 0 || let == '*') {
+ fmt = "%c - %.*s%s";
+ if (!txt)
+ txt = doname(obj);
+ txtlen = (int) strlen(txt);
+
+ if (cost != 0L || let == '*') {
/* if dot is true, we're doing Iu, otherwise Ix */
- Sprintf(li,
- iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
- : "%c - %-45s %6ld %s",
- (dot && use_invlet ? obj->invlet : let),
- (txt ? txt : doname(obj)), cost, currency(cost));
+ if (dot && use_invlet)
+ let = obj->invlet;
+ Sprintf(suffix, "%c%6ld %.50s", iflags.menu_tab_sep ? '\t' : ' ',
+ cost, currency(cost));
+ if (!iflags.menu_tab_sep) {
+ fmt = "%c - %-45.*s%s";
+ if (txtlen < 45)
+ txtlen = 45;
+ }
} else {
/* ordinary inventory display or pickup message */
- Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
- (txt ? txt : doname(obj)), (dot ? "." : ""));
+ if (use_invlet)
+ let = obj->invlet;
+ Strcpy(suffix, dot ? "." : "");
}
+ sfxlen = (int) strlen(suffix);
+ if (txtlen > BUFSZ - 1 - (4 + sfxlen)) /* 4: "c - " prefix */
+ txtlen = BUFSZ - 1 - (4 + sfxlen);
+ Sprintf(li, fmt, let, txtlen, txt, suffix);
+
if (savequan)
obj->quan = savequan;
diff --git a/src/isaac64.c b/src/isaac64.c
index 4d19335a31..8d0909250b 100644
--- a/src/isaac64.c
+++ b/src/isaac64.c
@@ -12,7 +12,6 @@
#include "config.h"
#ifdef USE_ISAAC64
-#include
#include
#include "isaac64.h"
diff --git a/src/mkobj.c b/src/mkobj.c
index 17265ff89c..9c1e624e2e 100644
--- a/src/mkobj.c
+++ b/src/mkobj.c
@@ -1105,8 +1105,10 @@ boolean artif;
}
/* unique objects may have an associated artifact entry */
- if (objects[otyp].oc_unique && !otmp->oartifact)
+ if (objects[otyp].oc_unique && !otmp->oartifact) {
+ /* mk_artifact() with otmp and A_NONE will never return NULL */
otmp = mk_artifact(otmp, (aligntyp) A_NONE);
+ }
otmp->owt = weight(otmp);
return otmp;
}
diff --git a/src/mplayer.c b/src/mplayer.c
index 2dba08e1bc..de3b4261a8 100644
--- a/src/mplayer.c
+++ b/src/mplayer.c
@@ -267,6 +267,7 @@ register boolean special;
otmp->oerodeproof = 1;
else if (!rn2(2))
otmp->greased = 1;
+ /* mk_artifact() with otmp and A_NONE will never return NULL */
if (special && rn2(2))
otmp = mk_artifact(otmp, A_NONE);
/* usually increase stack size if stackable weapon */
diff --git a/src/o_init.c b/src/o_init.c
index b2d28f50e8..5db3c416b2 100644
--- a/src/o_init.c
+++ b/src/o_init.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 o_init.c $NHDT-Date: 1545383615 2018/12/21 09:13:35 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.25 $ */
+/* NetHack 3.6 o_init.c $NHDT-Date: 1674864731 2023/01/28 00:12:11 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.27 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -10,6 +10,7 @@ STATIC_DCL void FDECL(setgemprobs, (d_level *));
STATIC_DCL void FDECL(shuffle, (int, int, BOOLEAN_P));
STATIC_DCL void NDECL(shuffle_all);
STATIC_DCL boolean FDECL(interesting_to_discover, (int));
+STATIC_DCL void FDECL(disco_append_typename, (char *, int));
STATIC_DCL char *FDECL(oclass_to_name, (CHAR_P, char *));
static NEARDATA short disco[NUM_OBJECTS] = DUMMY;
@@ -416,6 +417,32 @@ static short uniq_objs[] = {
BELL_OF_OPENING,
};
+/* append typename(dis) to buf[], possibly truncating in the process */
+STATIC_OVL void
+disco_append_typename(buf, dis)
+char *buf;
+int dis;
+{
+ unsigned len = (unsigned) strlen(buf);
+ char *p, *typnm = obj_typename(dis);
+
+ if (len + (unsigned) strlen(typnm) < BUFSZ) {
+ /* ordinary */
+ Strcat(buf, typnm);
+ } else if ((p = rindex(typnm, '(')) != 0
+ && p > typnm && p[-1] == ' ' && index(p, ')') != 0) {
+ /* typename() returned "really long user-applied name (actual type)"
+ and we want to truncate from "really long user-applied name" while
+ keeping " (actual type)" intact */
+ --p; /* back up to space in front of open paren */
+ (void) strncat(buf, typnm, BUFSZ - 1 - (len + (unsigned) strlen(p)));
+ Strcat(buf, p);
+ } else {
+ /* unexpected; just truncate from end of typename */
+ (void) strncat(buf, typnm, BUFSZ - 1 - len);
+ }
+}
+
/* the '\' command - show discovered object types */
int
dodiscovered() /* free after Robert Viduya */
@@ -459,9 +486,8 @@ dodiscovered() /* free after Robert Viduya */
let_to_name(oclass, FALSE, FALSE));
prev_class = oclass;
}
- Sprintf(buf, "%s %s",
- (objects[dis].oc_pre_discovered ? "*" : " "),
- obj_typename(dis));
+ Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
+ disco_append_typename(buf, dis);
putstr(tmpwin, 0, buf);
}
}
@@ -641,9 +667,8 @@ doclassdisco()
for (i = bases[(int) oclass];
i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i) {
if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
- Sprintf(buf, "%s %s",
- objects[dis].oc_pre_discovered ? "*" : " ",
- obj_typename(dis));
+ Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
+ disco_append_typename(buf, dis);
putstr(tmpwin, 0, buf);
++ct;
}
diff --git a/src/objnam.c b/src/objnam.c
index 7205bb4c46..063e8c95b2 100644
--- a/src/objnam.c
+++ b/src/objnam.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 objnam.c $NHDT-Date: 1583315888 2020/03/04 09:58:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.293 $ */
+/* NetHack 3.6 objnam.c $NHDT-Date: 1674864732 2023/01/28 00:12:12 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.259 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -16,6 +16,7 @@ STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
STATIC_DCL char *NDECL(nextobuf);
STATIC_DCL void FDECL(releaseobuf, (char *));
+STATIC_DCL void FDECL(xcalled, (char *, int, const char *, const char *));
STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
@@ -116,6 +117,7 @@ register int otyp;
if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
actualn = Japanese_item_name(otyp);
+ buf[0] = '\0';
switch (ocl->oc_class) {
case COIN_CLASS:
Strcpy(buf, "coin");
@@ -146,7 +148,7 @@ register int otyp;
else
Strcpy(buf, "amulet");
if (un)
- Sprintf(eos(buf), " called %s", un);
+ xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
if (dn)
Sprintf(eos(buf), " (%s)", dn);
return buf;
@@ -155,8 +157,8 @@ register int otyp;
Strcpy(buf, actualn);
if (GemStone(otyp))
Strcat(buf, " stone");
- if (un)
- Sprintf(eos(buf), " called %s", un);
+ if (un) /* 3: length of " (" + ")" which will enclose 'dn' */
+ xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
if (dn)
Sprintf(eos(buf), " (%s)", dn);
} else {
@@ -165,7 +167,7 @@ register int otyp;
Strcat(buf,
(ocl->oc_material == MINERAL) ? " stone" : " gem");
if (un)
- Sprintf(eos(buf), " called %s", un);
+ xcalled(buf, BUFSZ, "", un);
}
return buf;
}
@@ -176,8 +178,8 @@ register int otyp;
else
Sprintf(eos(buf), " of %s", actualn);
}
- if (un)
- Sprintf(eos(buf), " called %s", un);
+ if (un) /* 3: length of " (" + ")" which will enclose 'dn' */
+ xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
if (dn)
Sprintf(eos(buf), " (%s)", dn);
return buf;
@@ -410,6 +412,24 @@ boolean forward;
}
}
+/* add " called " to end of buf, truncating if necessary */
+STATIC_OVL void
+xcalled(buf, siz, pfx, sfx)
+char *buf; /* eos(obuf) or eos(&obuf[PREFIX]) */
+int siz; /* BUFSZ or BUFSZ-PREFIX */
+const char *pfx; /* usually class string, sometimes more specific */
+const char *sfx; /* user assigned type name */
+{
+ int bufsiz = siz - 1 - (int) strlen(buf),
+ pfxlen = (int) (strlen(pfx) + sizeof " called " - sizeof "");
+
+ if (pfxlen > bufsiz)
+ panic("xcalled: not enough room for prefix (%d > %d)",
+ pfxlen, bufsiz);
+
+ Sprintf(eos(buf), "%s called %.*s", pfx, bufsiz - pfxlen, sfx);
+}
+
char *
xname(obj)
struct obj *obj;
@@ -435,7 +455,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
actualn = Japanese_item_name(typ);
- /* As of 3.6.2: this used to be part of 'dn's initialization, but it
+ /* 3.6.2: this used to be part of 'dn's initialization, but it
needs to come after possibly overriding 'actualn' */
if (!dn)
dn = actualn;
@@ -478,7 +498,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
else if (nn)
Strcpy(buf, actualn);
else if (un)
- Sprintf(buf, "amulet called %s", un);
+ xcalled(buf, BUFSZ - PREFIX, "amulet", un);
else
Sprintf(buf, "%s amulet", dn);
break;
@@ -497,11 +517,9 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
Strcat(buf, dn);
else if (nn)
Strcat(buf, actualn);
- else if (un) {
- Strcat(buf, dn);
- Strcat(buf, " called ");
- Strcat(buf, un);
- } else
+ else if (un)
+ xcalled(buf, BUFSZ - PREFIX, dn, un);
+ else
Strcat(buf, dn);
if (typ == FIGURINE && omndx != NON_PM) {
@@ -631,8 +649,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
}
Strcat(buf, actualn);
} else {
- Strcat(buf, " called ");
- Strcat(buf, un);
+ xcalled(buf, BUFSZ - PREFIX, "", un);
}
} else {
Strcat(buf, dn);
@@ -647,8 +664,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
Strcat(buf, " of ");
Strcat(buf, actualn);
} else if (un) {
- Strcat(buf, " called ");
- Strcat(buf, un);
+ xcalled(buf, BUFSZ - PREFIX, "", un);
} else if (ocl->oc_magic) {
Strcat(buf, " labeled ");
Strcat(buf, dn);
@@ -663,7 +679,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
else if (nn)
Sprintf(buf, "wand of %s", actualn);
else if (un)
- Sprintf(buf, "wand called %s", un);
+ xcalled(buf, BUFSZ - PREFIX, "wand", un);
else
Sprintf(buf, "%s wand", dn);
break;
@@ -674,7 +690,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
else if (nn)
Strcpy(buf, actualn);
else if (un)
- Sprintf(buf, "novel called %s", un);
+ xcalled(buf, BUFSZ - PREFIX, "novel", un);
else
Sprintf(buf, "%s book", dn);
break;
@@ -686,7 +702,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
Strcpy(buf, "spellbook of ");
Strcat(buf, actualn);
} else if (un) {
- Sprintf(buf, "spellbook called %s", un);
+ xcalled(buf, BUFSZ - PREFIX, "spellbook", un);
} else
Sprintf(buf, "%s spellbook", dn);
break;
@@ -696,7 +712,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
else if (nn)
Sprintf(buf, "ring of %s", actualn);
else if (un)
- Sprintf(buf, "ring called %s", un);
+ xcalled(buf, BUFSZ - PREFIX, "ring", un);
else
Sprintf(buf, "%s ring", dn);
break;
@@ -707,7 +723,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
Strcpy(buf, rock);
} else if (!nn) {
if (un)
- Sprintf(buf, "%s called %s", rock, un);
+ xcalled(buf, BUFSZ - PREFIX, rock, un);
else
Sprintf(buf, "%s %s", dn, rock);
} else {
@@ -723,7 +739,17 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
if (pluralize)
Strcpy(buf, makeplural(buf));
- if (obj->otyp == T_SHIRT && program_state.gameover) {
+ /* additional information shown during end-of-game inventory disclosure */
+ if (obj->otyp == T_SHIRT && program_state.gameover
+ /* o_id will be 0 for wizard mode attribute disclosure (formatted
+ via from_what() -> ysimple_name() -> minimal_xname() -> xname()
+ by the enlightenment code; moot here since T-shirts don't affect
+ any attributes (but for 3.7, aprons will have comparable text) */
+ && obj->o_id
+ /* distantname is non-0 for do_screen_description() which is used
+ to produce tooltip text for HTMLDUMP (not supported by nethack) */
+ && !distantname
+ ) {
char tmpbuf[BUFSZ];
Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
@@ -732,7 +758,8 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */
if (has_oname(obj) && dknown) {
Strcat(buf, " named ");
nameit:
- Strcat(buf, ONAME(obj));
+ (void) strncat(buf, ONAME(obj),
+ BUFSZ - 1 - PREFIX - (unsigned) strlen(buf));
}
if (!strncmpi(buf, "the ", 4))
@@ -1684,7 +1711,7 @@ const char *str;
return strcpy(buf, "an []");
}
(void) just_an(buf, str);
- return strcat(buf, str);
+ return strncat(buf, str, BUFSZ - 1 - (unsigned) strlen(buf));
}
char *
@@ -1752,9 +1779,7 @@ const char *str;
Strcpy(buf, "the ");
else
buf[0] = '\0';
- Strcat(buf, str);
-
- return buf;
+ return strncat(buf, str, BUFSZ - 1 - (unsigned) strlen(buf));
}
char *
@@ -3166,10 +3191,12 @@ struct obj *no_wish;
*/
if ((p = strstri(bp, " named ")) != 0) {
*p = 0;
+ /* note: if 'name' is too long, oname() will truncate it */
name = p + 7;
}
if ((p = strstri(bp, " called ")) != 0) {
*p = 0;
+ /* note: if 'un' is too long, obj lookup just won't match anything */
un = p + 8;
/* "helmet called telepathy" is not "helmet" (a specific type)
* "shield called reflection" is not "shield" (a general type)
diff --git a/src/options.c b/src/options.c
index ffb7017978..561782cee3 100644
--- a/src/options.c
+++ b/src/options.c
@@ -685,6 +685,10 @@ initoptions()
*/
#endif
#endif /* SYSCF */
+ /* Carry out options that got deferred from early_options */
+ if (deferred_showpaths)
+ do_deferred_showpaths(0); /* does not return */
+
initoptions_finish();
}
@@ -2823,7 +2827,7 @@ boolean tinitial, tfrom_file;
return FALSE;
} else if ((op = string_for_opt(opts, negated)) != empty_optstr) {
#if defined(WIN32) && defined(TTY_GRAPHICS)
- set_altkeyhandler(op);
+ set_altkeyhandling(op);
#endif
} else
return FALSE;
@@ -5580,7 +5584,11 @@ boolean setinitial, setfromfile;
assign_graphics(PRIMARY);
preference_update("symset");
need_redraw = TRUE;
-
+#ifdef WIN32
+ } else if (!strcmp("altkeyhandler", optname)
+ || !strcmp("altkeyhandling", optname)) {
+ return set_keyhandling_via_option();
+#endif
} else {
/* didn't match any of the special options */
return FALSE;
@@ -5620,7 +5628,11 @@ char *buf;
#ifdef WIN32
else if (!strcmp(optname, "altkeyhandler"))
Sprintf(buf, "%s",
- iflags.altkeyhandler[0] ? iflags.altkeyhandler : "default");
+ (iflags.key_handling == ray_keyhandling)
+ ? "ray"
+ : (iflags.key_handling == nh340_keyhandling)
+ ? "340"
+ : "default");
#endif
#ifdef BACKWARD_COMPAT
else if (!strcmp(optname, "boulder"))
diff --git a/src/pager.c b/src/pager.c
index 7f14b0ffb9..c1c7b923d2 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -49,27 +49,34 @@ int c;
return FALSE;
}
-/*
- * Append new_str to the end of buf if new_str doesn't already exist as
- * a substring of buf. Return 1 if the string was appended, 0 otherwise.
- * It is expected that buf is of size BUFSZ.
- */
+/* Append " or "+new_str to the end of buf if new_str doesn't already exist
+ as a substring of buf. Return 1 if the string was appended, 0 otherwise.
+ It is expected that buf is of size BUFSZ. */
STATIC_OVL int
append_str(buf, new_str)
char *buf;
const char *new_str;
{
- int space_left; /* space remaining in buf */
-
+ static const char sep[] = " or ";
+ size_t oldlen, space_left;
+
if (strstri(buf, new_str))
- return 0;
-
- space_left = BUFSZ - strlen(buf) - 1;
- if (space_left < 1)
- return 0;
- (void) strncat(buf, " or ", space_left);
- (void) strncat(buf, new_str, space_left - 4);
- return 1;
+ return 0; /* already present */
+
+ oldlen = strlen(buf);
+ if (oldlen >= BUFSZ - 1) {
+ if (oldlen > BUFSZ - 1)
+ impossible("append_str: 'buf' contains %lu characters.",
+ (unsigned long) oldlen);
+ return 0; /* no space available */
+ }
+
+ /* some space available, but not necessarily enough for full append */
+ space_left = BUFSZ - 1 - oldlen; /* space remaining in buf */
+ (void) strncat(buf, sep, space_left);
+ if (space_left > sizeof sep - 1)
+ (void) strncat(buf, new_str, space_left - (sizeof sep - 1));
+ return 1; /* something was appended, possibly just part of " or " */
}
/* shared by monster probing (via query_objlist!) as well as lookat() */
diff --git a/src/pray.c b/src/pray.c
index 79369fc024..9f82dd6d34 100644
--- a/src/pray.c
+++ b/src/pray.c
@@ -1748,6 +1748,8 @@ dosacrifice()
/* The chance goes down as the number of artifacts goes up */
if (u.ulevel > 2 && u.uluck >= 0
&& !rn2(10 + (2 * u.ugifts * nartifacts))) {
+ /* mk_artifact() with NULL obj and a_align() arg
+ can return NULL */
otmp = mk_artifact((struct obj *) 0, a_align(u.ux, u.uy));
if (otmp) {
if (otmp->spe < 0)
diff --git a/src/priest.c b/src/priest.c
index ab20a8d7a6..5c56bc2cb6 100644
--- a/src/priest.c
+++ b/src/priest.c
@@ -622,7 +622,7 @@ register struct monst *priest;
&& (!(HProtection & INTRINSIC)
|| (u.ublessed < 20
&& (u.ublessed < 9 || !rn2(u.ublessed))))) {
- verbalize("Thy devotion has been rewarded.");
+ verbalize("Thou hast been rewarded for thy devotion.");
if (!(HProtection & INTRINSIC)) {
HProtection |= FROMOUTSIDE;
if (!u.ublessed)
diff --git a/src/weapon.c b/src/weapon.c
index 102740933f..1afd2697f9 100644
--- a/src/weapon.c
+++ b/src/weapon.c
@@ -843,9 +843,13 @@ register struct monst *mon;
newly_welded = mwelded(obj);
obj->owornmask &= ~W_WEP;
if (newly_welded) {
+ const char *mon_hand = mbodypart(mon, HAND);
+
+ if (bimanual(obj))
+ mon_hand = makeplural(mon_hand);
pline("%s %s to %s %s!", Tobjnam(obj, "weld"),
is_plural(obj) ? "themselves" : "itself",
- s_suffix(mon_nam(mon)), mbodypart(mon, HAND));
+ s_suffix(mon_nam(mon)), mon_hand);
obj->bknown = 1;
}
}
diff --git a/sys/unix/Makefile.dat b/sys/unix/Makefile.dat
index 00f6043961..9535f969e4 100644
--- a/sys/unix/Makefile.dat
+++ b/sys/unix/Makefile.dat
@@ -112,13 +112,20 @@ quest.dat: quest.txt ../util/makedefs
oracles: oracles.txt ../util/makedefs
../util/makedefs -h
-engrave: engrave.txt ../util/makedefs
+# note: 'makedefs -s' constructs three files at once: "epitaph", "engrave",
+# and "bogusmon", in that order, but traditional 'make' doesn't provide any
+# way for a Makefile to indicate that; make the third depend on the second
+# and the second depend on the first so that if someone runs parallel make
+# it will be forced to run three instances of 'makedefs -s' sequentially
+# rather than simultaneously; depending upon how 'make' checks timestamps,
+# this might result in building all three of them three times in a row
+# [that will still produce the correct result in the end, and the extra
+# overhead of doing it should be negligible]
+bogusmon: engrave bogusmon.txt ../util/makedefs
../util/makedefs -s
-
-epitaph: epitaph.txt ../util/makedefs
+engrave: epitaph engrave.txt ../util/makedefs
../util/makedefs -s
-
-bogusmon: bogusmon.txt ../util/makedefs
+epitaph: epitaph.txt ../util/makedefs
../util/makedefs -s
# note: 'options' should have already been made when include/date.h was created
diff --git a/sys/unix/Makefile.doc b/sys/unix/Makefile.doc
index 1d2f535328..de0fa59807 100644
--- a/sys/unix/Makefile.doc
+++ b/sys/unix/Makefile.doc
@@ -1,5 +1,5 @@
# NetHack Documentation Makefile.
-# NetHack 3.6 Makefile.doc $NHDT-Date: 1540625947 2018/10/27 07:39:07 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.17 $
+# NetHack 3.6 Makefile.doc $NHDT-Date: 1581732920 2020/02/15 02:15:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.20 $
# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
@@ -11,6 +11,9 @@ NHSROOT=..
MAKEDEFS = ../util/makedefs
+#STRIPBS=
+STRIPBS = ../util/stripbs
+
# Which version do we want to build? (XXX These are not used anywhere.)
GUIDEBOOK = Guidebook # regular ASCII file
#GUIDEBOOK = Guidebook.ps # PostScript file
@@ -19,21 +22,26 @@ GUIDEBOOK = Guidebook # regular ASCII file
# Some versions of col need -x to keep them from converting spaces to tabs;
# some versions of col don't do the conversion by default and don't
# recognize the option. Sigh.
-COLCMD = col -bx
-#COLCMD = col -b
+#COLCMD ?= col -bx
+#COLCMD ?= col -b
+COLCMD ?= $(STRIPBS)
# The command to use to generate a PostScript file
# PSCMD = ditroff | psdit
PSCMD = groff
-# Use the "cat" GUIDECMD if nroff and/or tbl and/or col are not installed
+#NROFF_SWITCHES = -c -tascii
+NROFF_SWITCHES = -c -Tascii -wall -Wtab -Wrange -Wel -Wscale
+
# Not appropriate for creating Guidebook.txt.
# GUIDECMD = cat Guidebook.txt
#
# Single page. Might need adjustment to .pl value
# GUIDECMD= $(GUIDE_PREFORMAT) | perl -pe 's/^(.mt)$$/.pl 4720v\n.in 0\n.po 8\n.ll 64m\n$$1/' | nroff -c -Tascii | $(COLCMD)
#
-GUIDECMD = $(GUIDE_PREFORMAT) | nroff -c -Tascii | $(COLCMD)
+GUIDECMD = $(GUIDE_PREFORMAT) | nroff $(NROFF_SWITCHES) | $(COLCMD)
+ONEPAGECMD = $(ONEPAGE_PREFORMAT) | nroff $(NROFF_SWITCHES) | $(COLCMD) \
+ | sed -e '/EOF--EOF/,12345D'
# Only generate output for the current configuration:
NHGREP = $(MAKEDEFS) --grep --input - --output -
@@ -43,10 +51,13 @@ NHGREP = $(MAKEDEFS) --grep --input - --output -
#NHGREP = cat
GUIDE_PREFORMAT = cat Guidebook.mn | $(NHGREP) | tbl tmac.n -
+# for Guidebook.dat, unpaginated version of Guidebook.txt
+ONEPAGE_PREFORMAT = cat Gbk-1pg-pfx.mn Guidebook.mn Gbk-1pg-sfx.mn \
+ | $(NHGREP) | tbl tmac.n -
# the basic guidebook
-Guidebook: Guidebook.mn tmac.n tmac.nh
- $(GUIDECMD) > Guidebook
+Guidebook: Guidebook.mn tmac.n tmac.nh $(MAKEDEFS) $(STRIPBS)
+ -$(GUIDECMD) > Guidebook
# Fancier output for those with ditroff, psdit and a PostScript printer.
Guidebook.ps: Guidebook.mn tmac.n tmac.nh
@@ -60,6 +71,10 @@ Guidebook.dvi: Guidebook.tex
latex Guidebook.tex
latex Guidebook.tex
+../util/makedefs:
+ ( cd .. ; $(MAKE) makedefs )
+../util/stripbs:
+ ( cd .. ; $(MAKE) stripbs )
GAME = nethack
MANDIR = /usr/man/man6
@@ -97,6 +112,9 @@ distrib: $(DISTRIB)
Guidebook.txt : Guidebook.mn tmac.n tmac.nh
$(GUIDECMD) > Guidebook.txt
+Guidebook.dat : Gbk-1pg-pfx.mn Gbk-1pg-sfx.mn Guidebook.mn tmac.n tmac.nh
+ $(ONEPAGECMD) > Guidebook.dat
+
MAN2TXT = $(NHGREP) | nroff -man - | $(COLCMD)
nethack.txt : nethack.6
cat nethack.6 | $(MAN2TXT) > nethack.txt
@@ -115,7 +133,7 @@ clean:
-rm -f Guidebook.aux Guidebook.log
spotless: clean
- -rm -f Guidebook Guidebook.ps Guidebook.dvi
+ -rm -f Guidebook Guidebook.dat Guidebook.ps Guidebook.dvi
maintainer-clean: spotless
-rm -f $(DISTRIB)
diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src
index 47ab9e0ce4..eeb30b9a06 100644
--- a/sys/unix/Makefile.src
+++ b/sys/unix/Makefile.src
@@ -991,7 +991,7 @@ decl.o: decl.c $(HACK_H)
detect.o: detect.c $(HACK_H) ../include/artifact.h
dig.o: dig.c $(HACK_H)
display.o: display.c $(HACK_H)
-dlb.o: dlb.c $(CONFIG_H) ../include/dlb.h
+dlb.o: dlb.c $(CONFIG_H) ../include/dlb.h ../include/patchlevel.h
do.o: do.c $(HACK_H) ../include/lev.h
do_name.o: do_name.c $(HACK_H)
do_wear.o: do_wear.c $(HACK_H)
@@ -1058,7 +1058,7 @@ rect.o: rect.c $(HACK_H)
region.o: region.c $(HACK_H) ../include/lev.h
restore.o: restore.c $(HACK_H) ../include/lev.h ../include/tcap.h
rip.o: rip.c $(HACK_H)
-rnd.o: rnd.c $(HACK_H)
+rnd.o: rnd.c $(HACK_H) ../include/isaac64.h ../include/integer.h
role.o: role.c $(HACK_H)
rumors.o: rumors.c $(HACK_H) ../include/lev.h ../include/dlb.h
save.o: save.c $(HACK_H) ../include/lev.h
diff --git a/sys/unix/Makefile.top b/sys/unix/Makefile.top
index ad7607cd98..795bb659b3 100644
--- a/sys/unix/Makefile.top
+++ b/sys/unix/Makefile.top
@@ -236,6 +236,11 @@ dofiles-nodlb:
-( cd $(INSTDIR) ; $(CHOWN) $(GAMEUID) $(DAT) ; \
$(CHGRP) $(GAMEGRP) $(DAT) ; \
chmod $(FILEPERM) $(DAT) )
+makedefs:
+ ( cd util ; $(MAKE) makedefs )
+
+stripbs:
+ ( cd util ; $(MAKE) stripbs )
update: $(GAME) recover $(VARDAT) dungeon spec_levs
# (don't yank the old version out from under people who're playing it)
diff --git a/sys/unix/Makefile.utl b/sys/unix/Makefile.utl
index 78e9d725f5..d955f7ac04 100644
--- a/sys/unix/Makefile.utl
+++ b/sys/unix/Makefile.utl
@@ -357,6 +357,15 @@ dlb: $(DLBOBJS)
dlb_main.o: dlb_main.c $(CONFIG_H) ../include/dlb.h ../include/date.h
$(CC) $(CFLAGS) -c dlb_main.c
+# dependencies for stripbs, an alternative filter utility to
+# strip "character + backspace + character" out of the generated
+# Guidebook, leaving only "character" in the final result.
+#
+stripbs: stripbs.o
+ $(CC) $(LFLAGS) -o stripbs stripbs.o
+
+stripbs.o: stripbs.c
+ $(CC) $(CFLAGS) -c stripbs.c
# dependencies for tile utilities
diff --git a/sys/unix/README.linux b/sys/unix/README.linux
index 24ab949056..864da755aa 100644
--- a/sys/unix/README.linux
+++ b/sys/unix/README.linux
@@ -61,6 +61,12 @@ If you have problems, send us some email.
nethack-bugs@nethack.org
+Prerequisite installations that are needed:
+ libncurses-dev
+ flex
+ bison
+ clang or gcc
+
Recommended steps:
1. cd sys/unix
diff --git a/sys/unix/hints/linux b/sys/unix/hints/linux
index 862915053c..fa7db7c237 100644
--- a/sys/unix/hints/linux
+++ b/sys/unix/hints/linux
@@ -34,6 +34,20 @@ CFLAGS+=-DCURSES_GRAPHICS
#CFLAGS+=-DSCORE_ON_BOTL
#CFLAGS+=-DMSGHANDLER
#CFLAGS+=-DTTY_TILES_ESCCODES
+#detection of clang vs gcc
+CCISCLANG := $(shell echo `$(CC) --version` | grep clang)
+ifneq "$(CCISCLANG)" ""
+CLANGGTEQ18 := $(shell expr `$(CC) -dumpversion | cut -f1 -d.` \>= 18)
+ifeq "$(CLANGGTEQ18)" "1"
+# clang-specific starts here
+CFLAGS+=-Wno-deprecated-non-prototype
+endif
+# clang-specific ends here
+else
+# gcc-specific starts here
+CFLAGS+=-Wno-old-style-definition -Wno-unused-result -Wno-format-overflow
+# gcc-specific ends here
+endif # clang-specific or gcc-specific ends here
LINK=$(CC)
# Only needed for GLIBC stack trace:
diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c
index 1e7880165d..09efb27f63 100644
--- a/sys/unix/unixmain.c
+++ b/sys/unix/unixmain.c
@@ -31,6 +31,7 @@ static void FDECL(chdirx, (const char *, BOOLEAN_P));
#endif /* CHDIR */
static boolean NDECL(whoami);
static void FDECL(process_options, (int, char **));
+static void NDECL(opt_terminate) NORETURN;
#ifdef _M_UNIX
extern void NDECL(check_sco_console);
@@ -115,14 +116,8 @@ char *argv[];
exit(EXIT_SUCCESS);
if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) {
-#ifdef CHDIR
- chdirx((char *) 0, 0);
-#endif
- iflags.initoptions_noterminate = TRUE;
- initoptions();
- iflags.initoptions_noterminate = FALSE;
- reveal_paths();
- exit(EXIT_SUCCESS);
+ deferred_showpaths = TRUE;
+ deferred_showpaths_dir = (char *) 0;
}
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
argc--;
@@ -807,4 +802,26 @@ sys_random_seed()
return seed;
}
+void
+after_opt_showpaths(dir)
+const char *dir UNUSED;
+{
+#ifdef CHDIR
+ chdirx((char *) 0, 0);
+#else
+ nhUse(dir);
+#endif
+ opt_terminate();
+}
+
+/* for command-line options that perform some immediate action and then
+ terminate the program without starting play, like 'nethack --version'
+ or 'nethack -s Zelda'; do some cleanup before that termination */
+static void
+opt_terminate(void)
+{
+ nh_terminate(EXIT_SUCCESS);
+ /*NOTREACHED*/
+}
+
/*unixmain.c*/
diff --git a/sys/vms/Makefile.src b/sys/vms/Makefile.src
index 745b21ad3d..a949801694 100644
--- a/sys/vms/Makefile.src
+++ b/sys/vms/Makefile.src
@@ -1,5 +1,5 @@
# NetHack Makefile (VMS) - for building nethack itself.
-# NetHack 3.6 Makefile.src $NHDT-Date: 1557701517 2019/05/12 22:51:57 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.36 $
+# NetHack 3.6 Makefile.src $NHDT-Date: 1683746779 2023/05/10 19:26:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.42 $
# Copyright (c) 2011 by Robert Patrick Rankin
# NetHack may be freely redistributed. See license for details.
@@ -133,7 +133,7 @@ RANDOBJ = isaac64.obj,random.obj
# Other things that have to be reconfigured are in vmsconf.h,
# and config.h
-VERSION = 3.6.6
+VERSION = 3.6.7
MAKEDEFS = $(UTL)makedefs.exe;
@@ -375,7 +375,7 @@ vmsunix.obj : $(VMS)vmsunix.c $(HACK_H)
vmsmisc.obj : $(VMS)vmsmisc.c $(VMS)oldcrtl.c $(CONFIG_H)
vmsfiles.obj : $(VMS)vmsfiles.c $(CONFIG_H)
vmsmail.obj : $(VMS)vmsmail.c $(CONFIG_H) $(INC)mail.h \
- $(INC)wintype.h $(INC)winprocs.h
+ $(INC)wintype.h $(INC)winprocs.h $(INC)color.h
# conditionally used code -- VMS always wants these
isaac64.obj : isaac64.c $(CONFIG_H) $(INC)isaac64.h
random.obj : random.c $(HACK_H)
@@ -384,7 +384,7 @@ random.c : $(SYSSHR)random.c
tclib.obj : tclib.c $(CONFIG_H)
tclib.c : $(SYSSHR)tclib.c
copy $(SYSSHR)tclib.c tclib.c
-# user interface code -- VMS uses tty or curses or both, not X11
+# user interface code -- VMS uses tty, not curses or X11
getline.obj : $(TTY)getline.c $(HACK_H) $(INC)func_tab.h
termcap.obj : $(TTY)termcap.c $(HACK_H) $(INC)tcap.h
topl.obj : $(TTY)topl.c $(HACK_H) $(INC)tcap.h
diff --git a/sys/vms/vmsbuild.com b/sys/vms/vmsbuild.com
index c48364b8bc..44735d1f35 100755
--- a/sys/vms/vmsbuild.com
+++ b/sys/vms/vmsbuild.com
@@ -1,5 +1,5 @@
$ ! vms/vmsbuild.com -- compile and link NetHack 3.6.* [pr]
-$ version_number = "3.6.6"
+$ version_number = "3.6.7"
$ ! $NHDT-Date: 1557701518 2019/05/12 22:51:58 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.23 $
$ ! Copyright (c) 2018 by Robert Patrick Rankin
$ ! NetHack may be freely redistributed. See license for details.
diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c
index 0a85720074..327d1af4d0 100644
--- a/sys/vms/vmsmain.c
+++ b/sys/vms/vmsmain.c
@@ -67,6 +67,12 @@ char *argv[];
dir = nh_getenv("HACKDIR");
#endif
if (argc > 1) {
+ if (argcheck(argc, argv, ARG_VERSION) == 2)
+ exit(EXIT_SUCCESS);
+
+ if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) {
+ deferred_showpaths = TRUE;
+ return;
#ifdef CHDIR
if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
/* avoid matching "-dec" for DECgraphics; since the man page
diff --git a/sys/winnt/.nethackrc.template b/sys/winnt/.nethackrc.template
index b2bacbd7f4..a4558e063a 100644
--- a/sys/winnt/.nethackrc.template
+++ b/sys/winnt/.nethackrc.template
@@ -27,13 +27,11 @@ OPTIONS=symset:IBMGraphics_2,roguesymset:RogueEpyx
#OPTIONS=windowtype:curses
#
# Keyboard handling
-# Different keyboard handlers can be loaded.
-# Default is nhdefkey.dll but you can override that.
-# Ray Chason's keyboard handler
-# OPTIONS=altkeyhandler:nhraykey.dll
+# Ray Chason's keyboard handling
+# OPTIONS=altkeyhandling:ray
#
# NetHack 3.4.0 keyboard handling
-# OPTIONS=altkeyhandler:nh340key.dll
+# OPTIONS=altkeyhandling:340
# *** Personal Preferences ***
# Some options to set personal preferences. Uncomment and change these to
diff --git a/sys/winnt/Install.nt b/sys/winnt/Install.nt
index 4ba30b4758..c9ce99e7b4 100644
--- a/sys/winnt/Install.nt
+++ b/sys/winnt/Install.nt
@@ -1,13 +1,13 @@
- Copyright (c) NetHack Development Team 1990-2019
+ Copyright (c) NetHack Development Team 1990-2023
NetHack may be freely redistributed. See license for details.
==============================================================
Instructions for compiling and installing
NetHack 3.6 on a Windows system
- (Windows 7/8.x/10 or later only)
+ (Windows 10/11 or later)
==============================================================
Last revision: $NHDT-Date: 1575245156 2019/12/02 00:05:56 $
-Credit for the porting of NetHack to the Win32 Console Subsystem goes to
+Credit for the porting of NetHack to the Win32 Console Subsystem goes to
the NT Porting Team started by Michael Allison.
Credit for the Win32 Graphical version of NetHack (aka "NetHack for
@@ -16,9 +16,9 @@ contributed the port.
Alex Kompel, Dion Nicolaas, Yitzhak Sapir, Derek S. Ray, Michael Allison,
Pasi Kallinen, Bart House, and Janet Walz contributed to the maintainance
-of the tty and graphical windows versions of NetHack 3.6.6.
+of the tty and graphical windows versions of NetHack 3.6.7.
-You can build a TTY version of NetHack and a Windows Graphical
+You can build a TTY version of NetHack and a Windows Graphical
version. You can use one of the following build environments:
o A copy of Microsoft Visual Studio 2017 Community Edition or
@@ -26,9 +26,9 @@ version. You can use one of the following build environments:
OR
- o (Untested for 3.6) A copy of MinGW. MinGW is a collection of header
- files and import libraries with which native Windows32 programs
- can be built; the MinGW distribution contains the GNU Compiler
+ o (Untested for 3.6) A copy of MinGW. MinGW is a collection of header
+ files and import libraries with which native Windows32 programs
+ can be built; the MinGW distribution contains the GNU Compiler
Collection. You can download MinGW at
http://www.mingw.org/
Earlier versions of MinGW will not allow you to build the Windows
@@ -38,22 +38,22 @@ version. You can use one of the following build environments:
| Directories for a Win32 NetHack build |
\---------------------------------------------/
-
+
(NetHack-top) ----------------------(optional-pdcurses-top)
| |
---------------------------------------------- --------------
| | | | | | | | |
- util dat doc include src sys win pdcurses wincon
+ util dat doc include src sys win pdcurses wincon
| |
- ------ --------
+ ------ --------
| | | |
share winnt tty win32
|
vs2017
-
+
/--------------------------------------------------------\
-| Building And Running Using Visual Studio 2017 |
+| Building And Running Using Visual Studio |
\--------------------------------------------------------/
If you are NOT using Visual Studio 2017 IDE, or you prefer to build
@@ -67,12 +67,19 @@ The Visual Studio 2017 NetHack solution file can be found here:
win\win32\vs2017\NetHack.sln
You can use that same win\win32\vs2017\NetHack.sln with Visual Studio 2019,
-but you may have to retarget the projects:
- Windows SDK Version: 10.0.17763.0 [ There have been some reports of
- difficulties if you instead choose
- "10.0 (latest installed version)" ]
+but you likely have to retarget the projects. The same would apply if you are
+trying to build using an even more recent version of Visual Studio as well.
+Note: If you already built NetHack previously with an older version of
+Visual Studio, manually delete the following subfolders of win\win32\vs2017:
+ obj
+ symbols
+
+ Windows SDK Version: 10.0.22000.0 [ There have been some reports of
+ difficulties if you choose
+ "10.0 (latest installed version)"
+ instead ]
Platform Toolset: Upgrade to v142
-
+
Before executing the steps to build listed in the next paragraph,
decide if you want to include optional curses window-port. See
@@ -94,18 +101,18 @@ using. Change to the directory win\win32\vs2017 and run "build.bat".
* Optional curses window-port support *
Since 3.6.2, the community patch for a window-port that uses curses has been
-incorporated into the NetHack source code tree. That window-port, which
+incorporated into the NetHack source code tree. That window-port, which
evolved from work originally done by Karl Garrison, has been used in several
NetHack variants and on nethack.alt.org and on www.hardfought.org/nethack/.
If you want to include the curses window-port support in your Visual Studio
build, you will have to first obtain the PDCurses sources from
https://github.com/wmcbrine/PDCurses
-and have them available prior to building NetHack. There are two ways to
-enable curses window-port support during the VS build: Either set the
-environment variable PDCURSES to a folder containing a PDCurses
+and have them available prior to building NetHack. There are two ways to
+enable curses window-port support during the VS build: Either set the
+environment variable PDCURSES to a folder containing a PDCurses
repository/source-tree
- OR
+ OR
Place the PDCurses folder alongside the NetHack source repository prior
to proceeding with steps 1 through 5 above.
@@ -117,8 +124,8 @@ to proceeding with steps 1 through 5 above.
--------------------------------------------------------------------------
-- Beginning of prerequisite step --
-The first step in building either version of NetHack via Makefile is to
-execute sys\winnt\nhsetup.bat to move some files to their required locations.
+The first step in building either version of NetHack via Makefile is to
+execute sys\winnt\nhsetup.bat to move some files to their required locations.
From the command prompt:
cd sys\winnt
@@ -141,25 +148,25 @@ command line using the Makefile approach:
NetHackW.
The executable for Console NetHack will be named NetHack.exe. The
-executable for Graphical NetHack will be named NetHackW.exe. The
+executable for Graphical NetHack will be named NetHackW.exe. The
Makefile configuration will build both; NetHackW.exe and NetHack.exe
will be able to use the same datafiles, save files and bones files.
-Since the last official release of NetHack, compilers and computer
+Since the last official release of NetHack, compilers and computer
architectures have evolved and you can now choose whether to build
a 32-bit x86 version, or a 64-bit x64 version. The default Makefile
-is set up for a 32-bit x86 version, but that's only because it will
+is set up for a 32-bit x86 version, but that's only because it will
run on the most number of existing Windows environments.
-NetHack's save files and bones files in the 3.6.6 release have not yet
-evolved enough to allow them to interchange between the 32-bit version
+NetHack's save files and bones files in the 3.6.7 release have not yet
+evolved enough to allow them to interchange between the 32-bit version
and the 64-bit version (or between different platforms). Hopefully
that will change in an upcoming release.
I. Dispelling the Myths:
Compiling NetHack for Windows is not as easy as it sounds, nor as hard
- as it looks, however it will behoove you to read this entire section
+ as it looks, however it will behoove you to read this entire section
through before beginning the task.
We have provided a Makefile for each of the following compilers:
@@ -168,10 +175,10 @@ I. Dispelling the Myths:
The Community Editions are fine and available at no cost
o MinGW 2.0 (with GCC 3.2)
- The Microsoft Visual Studio makefile was created for use
- with MS NMAKE which is provided with the Microsoft compiler.
+ The Microsoft Visual Studio makefile was created for use
+ with MS NMAKE which is provided with the Microsoft compiler.
The supplied Makefile may work with earlier versions of the Microsoft
- compiler, but that has not been tested.
+ compiler, but that has not been tested.
The GCC Makefile was created for use with GNU Make version 3.79.1,
which comes with the MinGW package.
@@ -185,41 +192,41 @@ II. To compile your copy of NetHack on a Windows machine:
Setting Up
-1. It almost goes without saying that you should make sure that your
+1. It almost goes without saying that you should make sure that your
tools are set up and running correctly. That includes ensuring that
all the necessary environment variables for the compiler environment
- are set correctly.
+ are set correctly.
- Change your current directory to the src subfolder of the nethack
+ Change your current directory to the src subfolder of the nethack
source tree.
cd src
- GCC
+ GCC
- For the GCC Makefile, add \bin to your path, where
+ For the GCC Makefile, add \bin to your path, where
is your MinGW root directory.).
- Change your current directory to src subfolder of the nethack
+ Change your current directory to src subfolder of the nethack
source tree.
cd src
2. Since 3.6.2, the community patch for an optional curses window-port
- has been incorporated into the NetHack source code tree. That
+ has been incorporated into the NetHack source code tree. That
window-port, which evolved from work originally done by Karl Garrison,
- has been used in several NetHack variants and on nethack.alt.org and
- on www.hardfought.org/nethack/. The optional curses window-port is
+ has been used in several NetHack variants and on nethack.alt.org and
+ on www.hardfought.org/nethack/. The optional curses window-port is
available for Windows, Mac OS X, and Unix (and also DOS).
If you want to include the optional curses window-port support in your
- command line Makefile build, you will have to first obtain the
+ command line Makefile build, you will have to first obtain the
PDCurses sources from https://github.com/wmcbrine/PDCurses
and have that source code tree available prior to building NetHack.
- Edit your Makefile and in Question 4 of the four decisions you can
+ Edit your Makefile and in Question 4 of the four decisions you can
make in there, uncomment these two lines:
ADD_CURSES=Y
PDCURSES_TOP=..\..\pdcurses
- Adjust the PDCURSES_TOP macro so that it points to the correct
+ Adjust the PDCURSES_TOP macro so that it points to the correct
location for the top of the PDCurses source tree if it differs from
the path shown.
@@ -228,8 +235,8 @@ Setting Up
subdirectories dat, doc, include, src, sys\share, sys\winnt,
win\tty, util.
- If you are including the optional Curses window port into your
- build,then you will need the top of the PDCurses sources in a
+ If you are including the optional Curses window port into your
+ build,then you will need the top of the PDCurses sources in a
folder parallel to the top of the NetHack folder (or you will need
to change the value of the PDCURSES_TOP macro in the Makefile to
specify the appropriate location.
@@ -257,7 +264,7 @@ Compiling
5. Now that everything is set up...
For the Visual Studio compiler, as mentioned above, you should now be
- at the command prompt to carry out the build and your current
+ at the command prompt to carry out the build and your current
directory should be the src subdirectory in the NetHack source tree.
In the src subdirectory, issue this command:
@@ -273,7 +280,7 @@ Compiling
particular machine of course, but you should be able to go for lunch
and return to find everything finished. The less memory, and slower
your machine, the longer the lunch you may take. :-)
-
+
In any case, it is likely that the command prompt window where you
are doing the compiling will be occupied for a while. If all goes
well, you will get an NetHack executable.
@@ -284,7 +291,7 @@ Notes:
your current directory to src and issue the appropriate command for
your compiler:
- For Microsoft compiler:
+ For Microsoft compiler:
nmake
For GCC:
@@ -299,19 +306,19 @@ Notes:
have to delete dgn_flex.c, dgn_yacc.c, lev_flex.c, and lev_yacc.c
from the util directory to ensure that they are remade.
-2. Depending on the build and compiler and tools used above, the
+2. Depending on the build and compiler and tools used above, the
executable produced by the TTY build is either:
- - a 32-bit (x86), flat-address space, non-overlayed .exe file,
+ - a 32-bit (x86), flat-address space, non-overlayed .exe file,
which should run on any recent Win32 environment.
or
- - a 64-bit (x64) .exe file,
+ - a 64-bit (x64) .exe file,
which should run on any 64-bit Windows O/S.
Note that saved games are NOT compatible between the 32-bit and the
64-bit versions at this time.
NetHack.exe is the tty version. NetHackW.exe is the graphical version.
-Play NetHack.
+Play NetHack.
PROBLEMS
diff --git a/sys/winnt/Makefile.gcc b/sys/winnt/Makefile.gcc
index f955075b38..10a234482f 100644
--- a/sys/winnt/Makefile.gcc
+++ b/sys/winnt/Makefile.gcc
@@ -134,12 +134,12 @@ TARGET_CPU=x86
#
#==============================================================================
-SKIP_NETHACKW=Y
+#SKIP_NETHACKW=Y
#==============================================================================
# The version of the game this Makefile was designed for
-NETHACK_VERSION="3.6.6"
+NETHACK_VERSION="3.6.7"
# A brief version for use in macros
NHV1=$(subst .,,$(NETHACK_VERSION))
@@ -317,7 +317,9 @@ VOBJ27 = $(O)worm.o $(O)worn.o $(O)write.o $(O)zap.o
DLBOBJ = $(O)dlb.o
-REGEX = $(O)cppregex.o
+REGEX = cppregex
+#REGEX = posixregex
+REGEXOBJ = $(O)$(REGEX).o
TTYOBJ = $(O)topl.o $(O)getline.o $(O)wintty.o
@@ -336,7 +338,7 @@ OBJS = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \
$(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \
$(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \
$(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \
- $(VOBJ26) $(VOBJ27) $(VOBJ28) $(VOBJ29) $(REGEX) \
+ $(VOBJ26) $(VOBJ27) $(VOBJ28) $(VOBJ29) $(REGEXOBJ) \
$(CURSESOBJ)
ifneq "$(SKIP_NETHACKW)" "Y"
@@ -375,8 +377,8 @@ endif
COMCTRL = comctl32.lib
-KEYDLLS = $(GAMEDIR)/nhdefkey.dll $(GAMEDIR)/nh340key.dll \
- $(GAMEDIR)/nhraykey.dll
+#KEYDLLS = $(GAMEDIR)/nhdefkey.dll $(GAMEDIR)/nh340key.dll \
+# $(GAMEDIR)/nhraykey.dll
TILEUTIL16 = $(UTIL)/tile2bmp.exe
TILEBMP16 = $(SRC)/tiles.bmp
@@ -483,14 +485,18 @@ endif
ifndef TRAVIS_COMPILER
cc = i686-w64-mingw32-gcc.exe
-cxx = g++
+cxx = i686-w64-mingw32-g++.exe
rc = windres
-link = i686-w64-mingw32-gcc.exe
else
cc = gcc
cxx = g++
rc = windres
-link = gcc
+endif
+
+ifeq "$(REGEX)" "cppregex"
+link = $(cxx)
+else
+link = $(cc)
endif
ifeq "$(WANT_WIN_QT4)" "Y"
@@ -507,12 +513,13 @@ cdebug =
linkdebug =
endif
+RESTARGET = --target=pe-i386
CFLAGSBASE = -c $(cflags) $(WINPINC) $(cdebug) $(CURSESDEF)
#LFLAGSBASEC = $(linkdebug)
#LFLAGSBASEG = $(linkdebug) -mwindows
baselibs = -lwinmm -lshell32 -lole32 -luuid
conlibs = -lgdi32 $(baselibs) $(BCRYPT)
-guilibs = -lcomctl32 $(baselibs)
+guilibs = -lgdi32 -lcomctl32 -lcomdlg32 -lwinmm -lshcore $(baselibs) $(BCRYPT)
ifeq "$(WANT_WIN_QT4)" "Y"
# Might be either Qt 4 or Qt 5
ifeq "$(HAVE_QT5)" "Y"
@@ -556,7 +563,7 @@ LFLAGSU = $(LFLAGSBASEC)
#==========================================
CFLAGS = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG) -DSAFEPROCS
-lflags = $(LFLAGSBASEC) $(linkdebuf)
+lflags = $(LFLAGSBASEC) $(linkdebug)
CXXFLAGS = $(CFLAGS)
@@ -716,7 +723,7 @@ $(QT4)/%.moc : $(QT4)/%.h
ifeq "$(SKIP_NETHACKW)" "Y"
NETHACKW_EXE =
else
-NETHACKW_EXE = $(GAMEDIR)/NetHack.exe
+NETHACKW_EXE = $(GAMEDIR)/NetHackW.exe
endif
SHELL=CMD.EXE
@@ -829,10 +836,10 @@ $(O)winres.o: $(TILEBMP16) $(MSWIN)/NetHackW.rc $(MSWIN)/mnsel.bmp \
$(MSWIN)/mnselcnt.bmp $(MSWIN)/mnunsel.bmp \
$(MSWIN)/petmark.bmp $(MSWIN)/pilemark.bmp $(MSWIN)/NetHack.ico $(MSWIN)/rip.bmp \
$(MSWIN)/splash.bmp
- $(rc) -o$@ --include-dir $(MSWIN) -i $(MSWIN)/NetHackW.rc
+ $(rc) -o$@ --include-dir $(MSWIN) $(RESTARGET) -DVIA_MAKE -i $(MSWIN)/NetHackW.rc
$(O)conres.o: $(MSWSYS)/console.rc $(MSWSYS)/NetHack.ico
- $(rc) -o$@ --include-dir $(MSWSYS) -i $(MSWSYS)/console.rc
+ $(rc) -o$@ --include-dir $(MSWSYS) $(RESTARGET) -i $(MSWSYS)/console.rc
#==========================================
# The game targets.
@@ -844,11 +851,11 @@ gamedir.tag:
test -d $(GAMEDIR) && echo directory created > $@
$(GAMEDIR)/NetHack.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)nttty.o $(O)guistub.o \
- $(ALLOBJ) $(TTYOBJ) $(GUIOBJ) $(O)conres.o $(KEYDLLS)
+ $(ALLOBJ) $(TTYOBJ) $(GUIOBJ) $(O)conres.o
@echo Linking $@...
$(link) $(lflags) -o$@ $(ALLOBJ) $(TTYOBJ) $(O)nttty.o $(O)tile.o \
$(O)guistub.o $(O)conres.o $(PDCLIB) $(conlibs) -static -lstdc++
- $(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
+ @$(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
# NetHackW
# full tty linkage libs:
@@ -860,11 +867,11 @@ $(GAMEDIR)/NetHack.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)nttty.o $(O)guistu
ifneq "$(SKIP_NETHACKW)" "Y"
$(GAMEDIR)/NetHackW.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)ttystub.o \
- $(ALLOBJ) $(TTYOBJ) $(GUIOBJ) $(O)winres.o $(KEYDLLS)
+ $(ALLOBJ) $(TTYOBJ) $(GUIOBJ) $(O)winres.o
@echo Linking $@...
$(link) $(lflags) -mwindows -o$@ $(ALLOBJ) $(GUIOBJ) $(O)tile.o $(O)ttystub.o \
$(O)winres.o $(PDCLIB) $(guilibs) -static -lstdc++
- $(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
+ @$(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
endif
$(O)nhdefkey.o:
@@ -1353,8 +1360,8 @@ endif
clean:
if exist initialchk del initialchk
- if exist $(O)install.tag del $(O)install.tag
- if exist $(O)utility.tag del $(O)utility.tag
+ $(subst /,\,if exist $(O)install.tag del $(O)install.tag)
+ $(subst /,\,if exist $(O)utility.tag del $(O)utility.tag)
ifneq "$(W_UTIL)" ""
if exist $(W_UTIL)\makedefs.exe del $(W_UTIL)\makedefs.exe
if exist $(W_UTIL)\levcomp.exe del $(W_UTIL)\levcomp.exe
@@ -1483,10 +1490,10 @@ endif
ifeq "$(WANT_WIN_QT4)" "Y"
# Qt dependencies
-$(GAMEDIR))/Qt5Core.dll : $(QT4_DIRECTORY)/bin/Qt5Core.dll
+$(GAMEDIR)/Qt5Core.dll : $(QT4_DIRECTORY)/bin/Qt5Core.dll
$(subst /,\,@copy $< $@ >nul)
-$(GAMEDIR))/Qt5Gui.dll : $(QT4_DIRECTORY)/bin/Qt5Gui.dll
+$(GAMEDIR)/Qt5Gui.dll : $(QT4_DIRECTORY)/bin/Qt5Gui.dll
$(subst /,\,@copy $< $@ >nul)
$(GAMEDIR)/Qt5Widgets.dll : $(QT4_DIRECTORY)/bin/Qt5Widgets.dll
diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc
index 8bd50868af..4061840b72 100644
--- a/sys/winnt/Makefile.msc
+++ b/sys/winnt/Makefile.msc
@@ -1,5 +1,5 @@
# NetHack 3.6 Makefile.msc $NHDT-Date: 1572748386 2019/11/03 02:33:06 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.167 $ */
-# Copyright (c) NetHack PC Development Team 1993-2019
+# Copyright (c) NetHack PC Development Team 1993-2023
#
#==============================================================================
# Build Tools Environment
@@ -93,7 +93,7 @@ DEBUGINFO = Y
#==============================================================================
#
# The version of the game this Makefile was designed for
-NETHACK_VERSION="3.6.6"
+NETHACK_VERSION="3.6.7"
# A brief version for use in macros
NHV=$(NETHACK_VERSION:.=)
@@ -274,8 +274,6 @@ GUIHDR = $(MSWIN)\mhaskyn.h $(MSWIN)\mhdlg.h $(MSWIN)\mhfont.h \
COMCTRL = comctl32.lib
-KEYDLLS = $(GAMEDIR)\nhdefkey.dll $(GAMEDIR)\nh340key.dll $(GAMEDIR)\nhraykey.dll
-
TILEUTIL16 = $(UTIL)\tile2bmp.exe
TILEBMP16 = $(SRC)\tiles.bmp
@@ -373,7 +371,27 @@ rc=Rc
# Visual Studio we are using. We set VSVER to 0000 to flag any version that
# is too old or untested.
#
-#NMAKE version 1421277022 is distributed with latest VS 2019
+#NMAKE version 1421277022 is distributed with latest VS 2019 at time of 3.6.6
+#NMAKE version 1434319370 is distributed with latest VS 2019 at time of 3.6.7
+
+# Before we get started, this section is used to determine the version of
+# Visual Studio we are using. We set VSVER to 0000 to flag any version that
+# is too old or untested.
+#
+# Recently tested versions:
+TESTEDVS2017 = 14.16.27048.0
+TESTEDVS2019 = 14.29.30147.0
+TESTEDVS2022 = 14.34.31937.0
+
+VS2017CUR = $(TESTEDVS2017:.=)
+VS2019CUR = $(TESTEDVS2019:.=)
+VS2022CUR = $(TESTEDVS2022:.=)
+VS2017UP1 = $(VS2017CUR) + 1
+VS2019UP1 = $(VS2019CUR) + 1
+VS2022UP1 = $(VS2022CUR) + 1
+VS20171ST = 1411000000
+VS20191ST = $(VS2017UP1)
+VS20221ST = $(VS2019UP1)
#!MESSAGE $(MAKEFLAGS)
#!MESSAGE $(MAKEDIR)
@@ -384,7 +402,8 @@ MAKEVERSION=$(MAKEVERSION: =)
#!MESSAGE $(_NMAKE_VER)
#!MESSAGE $(MAKEVERSION)
-VSNEWEST=2019
+VSSPECIAL=
+VSNEWEST=2022
!IF ($(MAKEVERSION) < 1000000000)
VSVER=0000 #untested ancient version
!ELSEIF ($(MAKEVERSION) > 1000000000) && ($(MAKEVERSION) < 1100000000)
@@ -395,21 +414,26 @@ VSVER=2012
VSVER=2013
!ELSEIF ($(MAKEVERSION) > 1400000000) && ($(MAKEVERSION) < 1411000000)
VSVER=2015
-!ELSEIF ($(MAKEVERSION) > 1411000000) && ($(MAKEVERSION) < 1416270312)
+!ELSEIF ($(MAKEVERSION) > $(VS20171ST)) && ($(MAKEVERSION) < $(VS2017UP1))
VSVER=2017
-!ELSEIF ($(MAKEVERSION) > 1416270311) && ($(MAKEVERSION) < 1421277023)
-VSVER=$(VSNEWEST)
-!ELSEIF ($(MAKEVERSION) > 1421277022)
+!ELSEIF ($(MAKEVERSION) > $(VS20191ST)) && ($(MAKEVERSION) < $(VS2019UP1))
+VSVER=2019
+!ELSEIF ($(MAKEVERSION) > $(VS20221ST)) && ($(MAKEVERSION) < $(VS2022UP1))
+VSVER=2022
+!ELSEIF ($(MAKEVERSION) > $(VS2022CUR))
VSVER=2999 #untested future version
!ENDIF
!IF ($(VSVER) >= 2012)
-!MESSAGE Autodetected Visual Studio $(VSVER)
-!ELSEIF ($(VSVER) == 2999
-!MESSAGE The version of Visual Studio is newer than the most recent at
-!MESSAGE the time this Makefile was crafted (Visual Studio $(VSNEWEST)).
-!MESSAGE Because it is newer we'll proceed expecting that the
-!MESSAGE VS$(VSNEWEST) processing will still work.
+!IF ($(VSVER) <= $(VSNEWEST))
+!MESSAGE Autodetected Visual Studio $(VSVER) $(VSSPECIAL)
+!ENDIF
+!ENDIF
+!IF ($(VSVER) == 2999)
+!MESSAGE The NMAKE version of this Visual Studio $(_NMAKE_VER) is newer than the
+!MESSAGE most recent at the time this Makefile was crafted (Visual Studio $(VSNEWEST)).
+!MESSAGE Because it is newer we'll proceed expecting that the VS$(VSNEWEST) processing
+!MESSAGE will still work.
!ELSEIF ($(VSVER) == 0000)
!MESSAGE The version of Visual Studio appears to be quite old, older
!MESSAGE than VS2010 which is the oldest supported version by this
@@ -754,7 +778,7 @@ $(O)NetHackW.res: $(TILEBMP16) $(MSWIN)\NetHackW.rc $(MSWIN)\mnsel.bmp \
$(MSWIN)\mnselcnt.bmp $(MSWIN)\mnunsel.bmp \
$(MSWIN)\petmark.bmp $(MSWIN)\pilemark.bmp $(MSWIN)\NetHack.ico $(MSWIN)\rip.bmp \
$(MSWIN)\splash.bmp
- @$(rc) -r -fo$@ -i$(MSWIN) -dNDEBUG $(MSWIN)\NetHackW.rc
+ @$(rc) -r -fo$@ -i$(MSWIN) -dNDEBUG -dVIA_MAKE $(MSWIN)\NetHackW.rc
$(O)console.res: $(MSWSYS)\console.rc $(MSWSYS)\NetHack.ico
@$(rc) -r -fo$@ -i$(MSWSYS) -dNDEBUG $(MSWSYS)\console.rc
@@ -845,63 +869,6 @@ $(O)gamedir.tag:
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
@echo directory created > $@
-$(O)nhdefkey.def:
- @echo LIBRARY $(@B) >$@
-! IF "$(TARGET_CPU)"=="x64" || "$(PROCESSOR_ARCHITECTURE)"=="x64"
-! ELSE
- @echo EXPORTS >>$@
- @echo ProcessKeystroke >>$@
- @echo NHkbhit >>$@
- @echo CheckInput >>$@
- @echo SourceWhere >>$@
- @echo SourceAuthor >>$@
- @echo KeyHandlerName >>$@
-! ENDIF
-
-$(GAMEDIR)\nhdefkey.dll : $(O)$(@B).o $(O)gamedir.tag $(O)$(@B).def
- @echo Linking $(@:\=/)
- @$(link) $(ldebug) /RELEASE /DLL user32.lib \
- /PDB:"$(O)$(@B).PDB" /MAP:"$(O)$(@B).map" /DEF:$(O)$(@B).def \
- /IMPLIB:$(O)$(@B).lib -out:$@ $(O)$(@B).o
-
-$(O)nh340key.def:
- @echo LIBRARY $(@B) >$@
-! IF "$(TARGET_CPU)"=="x64" || "$(PROCESSOR_ARCHITECTURE)"=="x64"
-! ELSE
- @echo EXPORTS >>$@
- @echo ProcessKeystroke >>$@
- @echo NHkbhit >>$@
- @echo CheckInput >>$@
- @echo SourceWhere >>$@
- @echo SourceAuthor >>$@
- @echo KeyHandlerName >>$@
-! ENDIF
-
-$(GAMEDIR)\nh340key.dll : $(O)$(@B).o $(O)gamedir.tag $(O)$(@B).def
- @echo Linking $(@:\=/)
- @$(link) $(ldebug) /RELEASE /NOLOGO /DLL user32.lib \
- /PDB:"$(O)$(@B).PDB" /MAP:"$(O)$(@B).map" /DEF:$(O)$(@B).def \
- /IMPLIB:$(O)$(@B).lib -out:$@ $(O)$(@B).o
-
-$(O)nhraykey.def:
- @echo LIBRARY $(@B) >$@
-! IF "$(TARGET_CPU)"=="x64" || "$(PROCESSOR_ARCHITECTURE)"=="x64"
-! ELSE
- @echo EXPORTS >>$@
- @echo ProcessKeystroke >>$@
- @echo NHkbhit >>$@
- @echo CheckInput >>$@
- @echo SourceWhere >>$@
- @echo SourceAuthor >>$@
- @echo KeyHandlerName >>$@
-! ENDIF
-
-$(GAMEDIR)\nhraykey.dll : $(O)$(@B).o $(O)gamedir.tag $(O)$(@B).def
- @echo Linking $(@:\=/)
- @$(link) $(ldebug) /RELEASE /NOLOGO /DLL user32.lib \
- /PDB:"$(O)$(@B).PDB" /MAP:"$(O)$(@B).map" /DEF:$(O)$(@B).def \
- /IMPLIB:$(O)$(@B).lib -out:$@ $(O)$(@B).o
-
#
# Secondary Targets.
#
@@ -1281,9 +1248,6 @@ $(O)pdcscrn.o : $(PDCURSES_HEADERS) $(PDCWINCON)\pdcscrn.c $(MSWSYS)\stub-pdcscr
spotless: clean
! IF ("$(OBJ)"!="")
if exist $(OBJ)\* rmdir $(OBJ) /s /Q
- if exist $(GAMEDIR)\nhdefkey.dll del $(GAMEDIR)\nhdefkey.dll
- if exist $(GAMEDIR)\nh340key.dll del $(GAMEDIR)\nh340key.dll
- if exist $(GAMEDIR)\nhraykey.dll del $(GAMEDIR)\nhraykey.dll
if exist $(GAMEDIR)\NetHack.exe del $(GAMEDIR)\NetHack.exe
if exist $(GAMEDIR)\NetHack.pdb del $(GAMEDIR)\NetHack.pdb
if exist $(GAMEDIR)\nhdat$(NHV) del $(GAMEDIR)\nhdat$(NHV)
@@ -1381,26 +1345,15 @@ clean:
if exist $(O)makedefs.MAP del $(O)makedefs.MAP
if exist $(O)makedefs.PDB del $(O)makedefs.PDB
if exist $(O)NetHack.MAP del $(O)NetHack.MAP
- if exist $(O)nh340key.def del $(O)nh340key.def
- if exist $(O)nh340key.exp del $(O)nh340key.exp
- if exist $(O)nh340key.lib del $(O)nh340key.lib
- if exist $(O)nh340key.map del $(O)nh340key.map
- if exist $(O)nh340key.PDB del $(O)nh340key.PDB
- if exist $(O)nhdefkey.def del $(O)nhdefkey.def
- if exist $(O)nhdefkey.exp del $(O)nhdefkey.exp
- if exist $(O)nhdefkey.lib del $(O)nhdefkey.lib
- if exist $(O)nhdefkey.map del $(O)nhdefkey.map
- if exist $(O)nhdefkey.PDB del $(O)nhdefkey.PDB
- if exist $(O)nhraykey.def del $(O)nhraykey.def
- if exist $(O)nhraykey.exp del $(O)nhraykey.exp
- if exist $(O)nhraykey.lib del $(O)nhraykey.lib
- if exist $(O)nhraykey.map del $(O)nhraykey.map
- if exist $(O)nhraykey.PDB del $(O)nhraykey.PDB
if exist $(O)envchk.tag del $(O)envchk.tag
if exist $(O)obj.tag del $(O)obj.tag
if exist $(O)sp_lev.tag del $(O)sp_lev.tag
if exist $(O)uudecode.MAP del $(O)uudecode.MAP
if exist $(O)uudecode.PDB del $(O)uudecode.PDB
+ if exist $(SRC)\tiles.bmp del $(SRC)\tiles.bmp
+ if exist $(O)console.res del $(O)console.res
+ if exist $(O)NetHack.res del $(O)NetHack.res
+ if exist $(O)NetHackW.res del $(O)NetHackW.res
rem
rem defer to the steps in ..\win\win32\levstuff.mak
rem
diff --git a/sys/winnt/console.rc b/sys/winnt/console.rc
index 427079edeb..5884c782b4 100644
--- a/sys/winnt/console.rc
+++ b/sys/winnt/console.rc
@@ -1,4 +1,4 @@
-/* NetHack 3.6 console.rc $NHDT-Date: 1575245149 2019/12/02 00:05:49 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.13 $ */
+/* NetHack 3.6 console.rc $NHDT-Date: 1601668518 2020/10/02 19:55:18 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.14 $ */
/* Copyright (c) Yitzhak Sapir, 2002. */
/* NetHack may be freely redistributed. See license for details. */
@@ -12,8 +12,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,6,3,0
- PRODUCTVERSION 3,6,3,0
+ FILEVERSION 3,6,7,0
+ PRODUCTVERSION 3,6,7,0
FILEFLAGSMASK 0x1fL
#ifdef _DEBUG
FILEFLAGS 0x9L
@@ -29,13 +29,13 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "NetHack for Windows - TTY Interface\0"
- VALUE "FileVersion", "3.6.3\0"
+ VALUE "FileVersion", "3.6.7\0"
VALUE "InternalName", "NetHack\0"
- VALUE "LegalCopyright", "Copyright (C) 1985 - 2019. By Stichting Mathematisch Centrum and M. Stephenson. See license for details.\0"
+ VALUE "LegalCopyright", "Copyright (C) 1985 - 2023. By Stichting Mathematisch Centrum and M. Stephenson. See license for details.\0"
VALUE "OriginalFilename", "NetHack.exe\0"
VALUE "PrivateBuild", "050102\0"
VALUE "ProductName", "NetHack\0"
- VALUE "ProductVersion", "3.6.3\0"
+ VALUE "ProductVersion", "3.6.7\0"
END
END
BLOCK "VarFileInfo"
diff --git a/sys/winnt/nh340key.c b/sys/winnt/nh340key.c
deleted file mode 100644
index a4faa80c16..0000000000
--- a/sys/winnt/nh340key.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* NetHack 3.6 nh340key.c $NHDT-Date: 1432512793 2015/05/25 00:13:13 $ $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
-/* Copyright (c) NetHack PC Development Team 2003 */
-/* NetHack may be freely redistributed. See license for details. */
-
-/*
- * This is the NetHack keystroke processing from NetHack 3.4.0.
- * It can be built as a run-time loadable dll (nh340key.dll),
- * placed in the same directory as the nethack.exe executable,
- * and loaded by specifying OPTIONS=altkeyhandler:nh340key
- * in defaults.nh
- */
-
-static char where_to_get_source[] = "http://www.nethack.org/";
-static char author[] = "The NetHack Development Team";
-
-#include "win32api.h"
-#include "hack.h"
-#include "wintty.h"
-
-extern HANDLE hConIn;
-extern INPUT_RECORD ir;
-char dllname[512];
-char *shortdllname;
-
-int FDECL(__declspec(dllexport) __stdcall ProcessKeystroke,
- (HANDLE hConIn, INPUT_RECORD *ir, boolean *valid,
- BOOLEAN_P numberpad, int portdebug));
-
-int WINAPI
-DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
-{
- char dlltmpname[512];
- char *tmp = dlltmpname, *tmp2;
- *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0';
- (void) strcpy(dllname, tmp);
- tmp2 = strrchr(dllname, '\\');
- if (tmp2) {
- tmp2++;
- shortdllname = tmp2;
- }
- return TRUE;
-}
-
-/*
- * Keyboard translation tables.
- * (Adopted from the MSDOS port)
- */
-
-#define KEYPADLO 0x47
-#define KEYPADHI 0x53
-
-#define PADKEYS (KEYPADHI - KEYPADLO + 1)
-#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
-
-#ifdef QWERTZ_SUPPORT
-/* when 'numberpad' is 0 and Cmd.swap_yz is True
- (signaled by setting 0x10 on boolean numpad argument)
- treat keypress of numpad 7 as 'z' rather than 'y' */
-static boolean qwertz = FALSE;
-#endif
-
-/*
- * Keypad keys are translated to the normal values below.
- * Shifted keypad keys are translated to the
- * shift values below.
- */
-
-static const struct pad {
- uchar normal, shift, cntrl;
-} keypad[PADKEYS] =
- {
- { 'y', 'Y', C('y') }, /* 7 */
- { 'k', 'K', C('k') }, /* 8 */
- { 'u', 'U', C('u') }, /* 9 */
- { 'm', C('p'), C('p') }, /* - */
- { 'h', 'H', C('h') }, /* 4 */
- { 'g', 'G', 'g' }, /* 5 */
- { 'l', 'L', C('l') }, /* 6 */
- { '+', 'P', C('p') }, /* + */
- { 'b', 'B', C('b') }, /* 1 */
- { 'j', 'J', C('j') }, /* 2 */
- { 'n', 'N', C('n') }, /* 3 */
- { 'i', 'I', C('i') }, /* Ins */
- { '.', ':', ':' } /* Del */
- },
- numpad[PADKEYS] = {
- { '7', M('7'), '7' }, /* 7 */
- { '8', M('8'), '8' }, /* 8 */
- { '9', M('9'), '9' }, /* 9 */
- { 'm', C('p'), C('p') }, /* - */
- { '4', M('4'), '4' }, /* 4 */
- { 'g', 'G', 'g' }, /* 5 */
- { '6', M('6'), '6' }, /* 6 */
- { '+', 'P', C('p') }, /* + */
- { '1', M('1'), '1' }, /* 1 */
- { '2', M('2'), '2' }, /* 2 */
- { '3', M('3'), '3' }, /* 3 */
- { 'i', 'I', C('i') }, /* Ins */
- { '.', ':', ':' } /* Del */
- };
-
-#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
-
-int __declspec(dllexport) __stdcall ProcessKeystroke(hConIn, ir, valid,
- numberpad, portdebug)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-boolean *valid;
-boolean numberpad;
-int portdebug;
-{
- int metaflags = 0, k = 0;
- int keycode, vk;
- unsigned char ch, pre_ch, mk = 0;
- unsigned short int scan;
- unsigned long shiftstate;
- int altseq = 0;
- const struct pad *kpad;
-
-#ifdef QWERTZ_SUPPORT
- if (numberpad & 0x10) {
- numberpad &= ~0x10;
- qwertz = TRUE;
- } else {
- qwertz = FALSE;
- }
-#endif
-
- shiftstate = 0L;
- ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- keycode = MapVirtualKey(vk, 2);
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
-
- if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
- if (ch || inmap(keycode, vk))
- altseq = 1;
- else
- altseq = -1; /* invalid altseq */
- }
- if (ch || (iskeypad(scan)) || (altseq > 0))
- *valid = TRUE;
- /* if (!valid) return 0; */
- /*
- * shiftstate can be checked to see if various special
- * keys were pressed at the same time as the key.
- * Currently we are using the ALT & SHIFT & CONTROLS.
- *
- * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
- * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
- * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
- * CAPSLOCK_ON, ENHANCED_KEY
- *
- * are all valid bit masks to use on shiftstate.
- * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
- * left control key was pressed with the keystroke.
- */
- if (iskeypad(scan)) {
- kpad = numberpad ? numpad : keypad;
- if (shiftstate & SHIFT_PRESSED) {
- ch = kpad[scan - KEYPADLO].shift;
- } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
- ch = kpad[scan - KEYPADLO].cntrl;
- } else {
- ch = kpad[scan - KEYPADLO].normal;
- }
-#ifdef QWERTZ_SUPPORT
- /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting,
- 'numberpad' will be 0; core swaps y to zap, z to move northwest;
- we want numpad 7 to move northwest, so when qwertz is set,
- tell core that user who types numpad 7 typed z rather than y */
- if (qwertz && kpad[scan - KEYPADLO].normal == 'y')
- ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */
-#endif /*QWERTZ_SUPPORT*/
- } else if (altseq > 0) { /* ALT sequence */
- if (vk == 0xBF)
- ch = M('?');
- else
- ch = M(tolower((uchar) keycode));
- }
- if (ch == '\r')
- ch = '\n';
-#ifdef PORT_DEBUG
- if (portdebug) {
- char buf[BUFSZ];
- Sprintf(buf,
- "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, sh=0x%X (ESC to end)",
- shortdllname, ch, scan, vk, shiftstate);
- fprintf(stdout, "\n%s", buf);
- }
-#endif
- return ch;
-}
-
-int __declspec(dllexport) __stdcall NHkbhit(hConIn, ir)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-{
- int done = 0; /* true = "stop searching" */
- int retval; /* true = "we had a match" */
- DWORD count;
- unsigned short int scan;
- unsigned char ch;
- unsigned long shiftstate;
- int altseq = 0, keycode, vk;
- done = 0;
- retval = 0;
- while (!done) {
- count = 0;
- PeekConsoleInput(hConIn, ir, 1, &count);
- if (count > 0) {
- if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
- ch = ir->Event.KeyEvent.uChar.AsciiChar;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- keycode = MapVirtualKey(vk, 2);
- if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
- if (ch || inmap(keycode, vk))
- altseq = 1;
- else
- altseq = -1; /* invalid altseq */
- }
- if (ch || iskeypad(scan) || altseq) {
- done = 1; /* Stop looking */
- retval = 1; /* Found what we sought */
- } else {
- /* Strange Key event; let's purge it to avoid trouble */
- ReadConsoleInput(hConIn, ir, 1, &count);
- }
-
- } else if ((ir->EventType == MOUSE_EVENT
- && (ir->Event.MouseEvent.dwButtonState
- & MOUSEMASK))) {
- done = 1;
- retval = 1;
- }
-
- else /* Discard it, it's an insignificant event */
- ReadConsoleInput(hConIn, ir, 1, &count);
- } else /* There are no events in console event queue */ {
- done = 1; /* Stop looking */
- retval = 0;
- }
- }
- return retval;
-}
-
-int __declspec(dllexport) __stdcall CheckInput(hConIn, ir, count, numpad,
- mode, mod, cc)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-DWORD *count;
-boolean numpad;
-int mode;
-int *mod;
-coord *cc;
-{
-#if defined(SAFERHANGUP)
- DWORD dwWait;
-#endif
- int ch;
- boolean valid = 0, done = 0;
-
-#ifdef QWERTZ_SUPPORT
- if (numpad & 0x10) {
- numpad &= ~0x10;
- qwertz = TRUE;
- } else {
- qwertz = FALSE;
- }
-#endif
- while (!done) {
-#if defined(SAFERHANGUP)
- dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
- INFINITE, // waits indefinitely
- TRUE); // alertable wait enabled
- if (dwWait == WAIT_FAILED)
- return '\033';
-#endif
- ReadConsoleInput(hConIn, ir, 1, count);
- if (mode == 0) {
- if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
-#ifdef QWERTZ_SUPPORT
- if (qwertz)
- numpad |= 0x10;
-#endif
- ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
-#ifdef QWERTZ_SUPPORT
- numpad &= ~0x10;
-#endif
- done = valid;
- }
- } else {
- if (count > 0) {
- if (ir->EventType == KEY_EVENT
- && ir->Event.KeyEvent.bKeyDown) {
- ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
- if (valid)
- return ch;
- } else if (ir->EventType == MOUSE_EVENT) {
- if ((ir->Event.MouseEvent.dwEventFlags == 0)
- && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
- cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
- cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
-
- if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
- *mod = CLICK_1;
- else if (ir->Event.MouseEvent.dwButtonState
- & RIGHTBUTTON)
- *mod = CLICK_2;
-#if 0 /* middle button */
- else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
- *mod = CLICK_3;
-#endif
- return 0;
- }
- }
- } else
- done = 1;
- }
- }
- return mode ? 0 : ch;
-}
-
-int __declspec(dllexport) __stdcall SourceWhere(buf)
-char **buf;
-{
- if (!buf)
- return 0;
- *buf = where_to_get_source;
- return 1;
-}
-
-int __declspec(dllexport) __stdcall SourceAuthor(buf)
-char **buf;
-{
- if (!buf)
- return 0;
- *buf = author;
- return 1;
-}
-
-int __declspec(dllexport) __stdcall KeyHandlerName(buf, full)
-char **buf;
-int full;
-{
- if (!buf)
- return 0;
- if (full)
- *buf = dllname;
- else
- *buf = shortdllname;
- return 1;
-}
diff --git a/sys/winnt/nhdefkey.c b/sys/winnt/nhdefkey.c
deleted file mode 100644
index e40cf6a1e0..0000000000
--- a/sys/winnt/nhdefkey.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/* NetHack 3.6 nhdefkey.c $NHDT-Date: 1432512793 2015/05/25 00:13:13 $ $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
-/* Copyright (c) NetHack PC Development Team 2003 */
-/* NetHack may be freely redistributed. See license for details. */
-
-/*
- * This is the default NetHack keystroke processing.
- * It can be built as a run-time loadable dll (nhdefkey.dll).
- * Alternative keystroke handlers can be built using the
- * entry points in this file as a template.
- *
- * Use the defaults.nh "altkeyhandler" option to set a
- * different dll name (without the ".DLL" extension) to
- * get different processing. Ensure that the dll referenced
- * in defaults.nh exists in the same directory as NetHack in
- * order for it to load successfully.
- *
- */
-
-static char where_to_get_source[] = "http://www.nethack.org/";
-static char author[] = "The NetHack Development Team";
-
-#include "win32api.h"
-#include "hack.h"
-#include "wintty.h"
-
-extern HANDLE hConIn;
-extern INPUT_RECORD ir;
-extern struct sinfo program_state;
-
-char dllname[512];
-char *shortdllname;
-
-int FDECL(__declspec(dllexport) __stdcall ProcessKeystroke,
- (HANDLE hConIn, INPUT_RECORD *ir, boolean *valid,
- BOOLEAN_P numberpad, int portdebug));
-
-int WINAPI
-DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
-{
- char dlltmpname[512];
- char *tmp = dlltmpname, *tmp2;
- *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0';
- (void) strcpy(dllname, tmp);
- tmp2 = strrchr(dllname, '\\');
- if (tmp2) {
- tmp2++;
- shortdllname = tmp2;
- }
- return TRUE;
-}
-
-/*
- * Keyboard translation tables.
- * (Adopted from the MSDOS port)
- */
-
-#define KEYPADLO 0x47
-#define KEYPADHI 0x53
-
-#define PADKEYS (KEYPADHI - KEYPADLO + 1)
-#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
-
-#ifdef QWERTZ_SUPPORT
-/* when 'numberpad' is 0 and Cmd.swap_yz is True
- (signaled by setting 0x10 on boolean numpad argument)
- treat keypress of numpad 7 as 'z' rather than 'y' */
-static boolean qwertz = FALSE;
-#endif
-
-/*
- * Keypad keys are translated to the normal values below.
- * Shifted keypad keys are translated to the
- * shift values below.
- */
-
-static const struct pad {
- uchar normal, shift, cntrl;
-} keypad[PADKEYS] =
- {
- { 'y', 'Y', C('y') }, /* 7 */
- { 'k', 'K', C('k') }, /* 8 */
- { 'u', 'U', C('u') }, /* 9 */
- { 'm', C('p'), C('p') }, /* - */
- { 'h', 'H', C('h') }, /* 4 */
- { 'g', 'G', 'g' }, /* 5 */
- { 'l', 'L', C('l') }, /* 6 */
- { '+', 'P', C('p') }, /* + */
- { 'b', 'B', C('b') }, /* 1 */
- { 'j', 'J', C('j') }, /* 2 */
- { 'n', 'N', C('n') }, /* 3 */
- { 'i', 'I', C('i') }, /* Ins */
- { '.', ':', ':' } /* Del */
- },
- numpad[PADKEYS] = {
- { '7', M('7'), '7' }, /* 7 */
- { '8', M('8'), '8' }, /* 8 */
- { '9', M('9'), '9' }, /* 9 */
- { 'm', C('p'), C('p') }, /* - */
- { '4', M('4'), '4' }, /* 4 */
- { '5', M('5'), '5' }, /* 5 */
- { '6', M('6'), '6' }, /* 6 */
- { '+', 'P', C('p') }, /* + */
- { '1', M('1'), '1' }, /* 1 */
- { '2', M('2'), '2' }, /* 2 */
- { '3', M('3'), '3' }, /* 3 */
- { '0', M('0'), '0' }, /* Ins */
- { '.', ':', ':' } /* Del */
- };
-
-#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
-
-static BYTE KeyState[256];
-
-int __declspec(dllexport) __stdcall ProcessKeystroke(hConIn, ir, valid,
- numberpad, portdebug)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-boolean *valid;
-boolean numberpad;
-int portdebug;
-{
- int metaflags = 0, k = 0;
- int keycode, vk;
- unsigned char ch, pre_ch, mk = 0;
- unsigned short int scan;
- unsigned long shiftstate;
- int altseq = 0;
- const struct pad *kpad;
-
-#ifdef QWERTZ_SUPPORT
- if (numberpad & 0x10) {
- numberpad &= ~0x10;
- qwertz = TRUE;
- } else {
- qwertz = FALSE;
- }
-#endif
- shiftstate = 0L;
- ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- keycode = MapVirtualKey(vk, 2);
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
- KeyState[VK_SHIFT] = (shiftstate & SHIFT_PRESSED) ? 0x81 : 0;
- KeyState[VK_CONTROL] =
- (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ? 0x81 : 0;
- KeyState[VK_CAPITAL] = (shiftstate & CAPSLOCK_ON) ? 0x81 : 0;
-
- if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
- if (ch || inmap(keycode, vk))
- altseq = 1;
- else
- altseq = -1; /* invalid altseq */
- }
- if (ch || (iskeypad(scan)) || (altseq > 0))
- *valid = TRUE;
- /* if (!valid) return 0; */
- /*
- * shiftstate can be checked to see if various special
- * keys were pressed at the same time as the key.
- * Currently we are using the ALT & SHIFT & CONTROLS.
- *
- * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
- * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
- * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
- * CAPSLOCK_ON, ENHANCED_KEY
- *
- * are all valid bit masks to use on shiftstate.
- * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
- * left control key was pressed with the keystroke.
- */
- if (iskeypad(scan)) {
- kpad = numberpad ? numpad : keypad;
- if (shiftstate & SHIFT_PRESSED) {
- ch = kpad[scan - KEYPADLO].shift;
- } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
- ch = kpad[scan - KEYPADLO].cntrl;
- } else {
- ch = kpad[scan - KEYPADLO].normal;
- }
-#ifdef QWERTZ_SUPPORT
- /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting,
- 'numberpad' will be 0; core swaps y to zap, z to move northwest;
- we want numpad 7 to move northwest, so when qwertz is set,
- tell core that user who types numpad 7 typed z rather than y */
- if (qwertz && kpad[scan - KEYPADLO].normal == 'y')
- ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */
-#endif /*QWERTZ_SUPPORT*/
- } else if (altseq > 0) { /* ALT sequence */
- if (vk == 0xBF)
- ch = M('?');
- else
- ch = M(tolower((uchar) keycode));
- }
- /* Attempt to work better with international keyboards. */
- else {
- WORD chr[2];
- k = ToAscii(vk, scan, KeyState, chr, 0);
- if (k <= 2)
- switch (k) {
- case 2: /* two characters */
- ch = (unsigned char) chr[1];
- *valid = TRUE;
- break;
- case 1: /* one character */
- ch = (unsigned char) chr[0];
- *valid = TRUE;
- break;
- case 0: /* no translation */
- default: /* negative */
- *valid = FALSE;
- }
- }
- if (ch == '\r')
- ch = '\n';
-#ifdef PORT_DEBUG
- if (portdebug) {
- char buf[BUFSZ];
- Sprintf(buf, "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, pre=%d, sh=0x%X, "
- "ta=%d (ESC to end)",
- shortdllname, ch, scan, vk, pre_ch, shiftstate, k);
- fprintf(stdout, "\n%s", buf);
- }
-#endif
- return ch;
-}
-
-int __declspec(dllexport) __stdcall NHkbhit(hConIn, ir)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-{
- int done = 0; /* true = "stop searching" */
- int retval; /* true = "we had a match" */
- DWORD count;
- unsigned short int scan;
- unsigned char ch;
- unsigned long shiftstate;
- int altseq = 0, keycode, vk;
- done = 0;
- retval = 0;
- while (!done) {
- count = 0;
- PeekConsoleInput(hConIn, ir, 1, &count);
- if (count > 0) {
- if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
- ch = ir->Event.KeyEvent.uChar.AsciiChar;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- keycode = MapVirtualKey(vk, 2);
- if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
- if (ch || inmap(keycode, vk))
- altseq = 1;
- else
- altseq = -1; /* invalid altseq */
- }
- if (ch || iskeypad(scan) || altseq) {
- done = 1; /* Stop looking */
- retval = 1; /* Found what we sought */
- } else {
- /* Strange Key event; let's purge it to avoid trouble */
- ReadConsoleInput(hConIn, ir, 1, &count);
- }
-
- } else if ((ir->EventType == MOUSE_EVENT
- && (ir->Event.MouseEvent.dwButtonState
- & MOUSEMASK))) {
- done = 1;
- retval = 1;
- }
-
- else /* Discard it, it's an insignificant event */
- ReadConsoleInput(hConIn, ir, 1, &count);
- } else /* There are no events in console event queue */ {
- done = 1; /* Stop looking */
- retval = 0;
- }
- }
- return retval;
-}
-
-int __declspec(dllexport) __stdcall CheckInput(hConIn, ir, count, numpad,
- mode, mod, cc)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-DWORD *count;
-boolean numpad;
-int mode;
-int *mod;
-coord *cc;
-{
-#if defined(SAFERHANGUP)
- DWORD dwWait;
-#endif
- int ch;
- boolean valid = 0, done = 0;
-
-#ifdef QWERTZ_SUPPORT
- if (numpad & 0x10) {
- numpad &= ~0x10;
- qwertz = TRUE;
- } else {
- qwertz = FALSE;
- }
-#endif
- while (!done) {
-#if defined(SAFERHANGUP)
- dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
- INFINITE, // waits indefinitely
- TRUE); // alertable wait enabled
- if (dwWait == WAIT_FAILED)
- return '\033';
-#endif
- ReadConsoleInput(hConIn, ir, 1, count);
- if (mode == 0) {
- if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
- ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
- done = valid;
- }
- } else {
- if (count > 0) {
- if (ir->EventType == KEY_EVENT
- && ir->Event.KeyEvent.bKeyDown) {
-#ifdef QWERTZ_SUPPORT
- if (qwertz)
- numpad |= 0x10;
-#endif
- ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
-#ifdef QWERTZ_SUPPORT
- numpad &= ~0x10;
-#endif
- if (valid)
- return ch;
- } else if (ir->EventType == MOUSE_EVENT) {
- if ((ir->Event.MouseEvent.dwEventFlags == 0)
- && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
- cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
- cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
-
- if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
- *mod = CLICK_1;
- else if (ir->Event.MouseEvent.dwButtonState
- & RIGHTBUTTON)
- *mod = CLICK_2;
-#if 0 /* middle button */
- else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
- *mod = CLICK_3;
-#endif
- return 0;
- }
- }
- } else
- done = 1;
- }
- }
- return mode ? 0 : ch;
-}
-
-int __declspec(dllexport) __stdcall SourceWhere(buf)
-char **buf;
-{
- if (!buf)
- return 0;
- *buf = where_to_get_source;
- return 1;
-}
-
-int __declspec(dllexport) __stdcall SourceAuthor(buf)
-char **buf;
-{
- if (!buf)
- return 0;
- *buf = author;
- return 1;
-}
-
-int __declspec(dllexport) __stdcall KeyHandlerName(buf, full)
-char **buf;
-int full;
-{
- if (!buf)
- return 0;
- if (full)
- *buf = dllname;
- else
- *buf = shortdllname;
- return 1;
-}
diff --git a/sys/winnt/nhraykey.c b/sys/winnt/nhraykey.c
deleted file mode 100644
index 7ce4e0e50d..0000000000
--- a/sys/winnt/nhraykey.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/* NetHack 3.6 nhraykey.c $NHDT-Date: 1457207047 2016/03/05 19:44:07 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.16 $ */
-/* Copyright (c) NetHack PC Development Team 2003 */
-/* NetHack may be freely redistributed. See license for details. */
-
-/*
- * Keystroke handling contributed by Ray Chason.
- * The following text was written by Ray Chason.
- *
- * The problem
- * ===========
- *
- * The console-mode Nethack wants both keyboard and mouse input. The
- * problem is that the Windows API provides no easy way to get mouse input
- * and also keyboard input properly translated according to the user's
- * chosen keyboard layout.
- *
- * The ReadConsoleInput function returns a stream of keyboard and mouse
- * events. Nethack is interested in those events that represent a key
- * pressed, or a click on a mouse button. The keyboard events from
- * ReadConsoleInput are not translated according to the keyboard layout,
- * and do not take into account the shift, control, or alt keys.
- *
- * The PeekConsoleInput function works similarly to ReadConsoleInput,
- * except that it does not remove an event from the queue and it returns
- * instead of blocking when the queue is empty.
- *
- * A program can also use ReadConsole to get a properly translated stream
- * of characters. Unfortunately, ReadConsole does not return mouse events,
- * does not distinguish the keypad from the main keyboard, does not return
- * keys shifted with Alt, and does not even return the ESC key when
- * pressed.
- *
- * We want both the functionality of ReadConsole and the functionality of
- * ReadConsoleInput. But Microsoft didn't seem to think of that.
- *
- *
- * The solution, in the original code
- * ==================================
- *
- * The original 3.4.1 distribution tries to get proper keyboard translation
- * by passing keyboard events to the ToAscii function. This works, to some
- * extent -- it takes the shift key into account, and it processes dead
- * keys properly. But it doesn't take non-US keyboards into account. It
- * appears that ToAscii is meant for windowed applications, and does not
- * have enough information to do its job properly in a console application.
- *
- *
- * The Finnish keyboard patch
- * ==========================
- *
- * This patch adds the "subkeyvalue" option to the defaults.nh file. The
- * user can then add OPTIONS=sukeyvalue:171/92, for instance, to replace
- * the 171 character with 92, which is \. This works, once properly
- * configured, but places too much burden on the user. It also bars the
- * use of the substituted characters in naming objects or monsters.
- *
- *
- * The solution presented here
- * ===========================
- *
- * The best way I could find to combine the functionality of ReadConsole
- * with that of ReadConsoleInput is simple in concept. First, call
- * PeekConsoleInput to get the first event. If it represents a key press,
- * call ReadConsole to retrieve the key. Otherwise, pop it off the queue
- * with ReadConsoleInput and, if it's a mouse click, return it as such.
- *
- * But the Devil, as they say, is in the details. The problem is in
- * recognizing an event that ReadConsole will return as a key. We don't
- * want to call ReadConsole unless we know that it will immediately return:
- * if it blocks, the mouse and the Alt sequences will cease to function
- * until it returns.
- *
- * Separating process_keystroke into two functions, one for commands and a
- * new one, process_keystroke2, for answering prompts, makes the job a lot
- * easier. process_keystroke2 doesn't have to worry about mouse events or
- * Alt sequences, and so the consequences are minor if ReadConsole blocks.
- * process_keystroke, OTOH, never needs to return a non-ASCII character
- * that was read from ReadConsole; it returns bytes with the high bit set
- * only in response to an Alt sequence.
- *
- * So in process_keystroke, before calling ReadConsole, a bogus key event
- * is pushed on the queue. This event causes ReadConsole to return, even
- * if there was no other character available. Because the bogus key has
- * the eighth bit set, it is filtered out. This is not done in
- * process_keystroke2, because that would render dead keys unusable.
- *
- * A separate process_keystroke2 can also process the numeric keypad in a
- * way that makes sense for prompts: just return the corresponding symbol,
- * and pay no mind to number_pad or the num lock key.
- *
- * The recognition of Alt sequences is modified, to support the use of
- * characters generated with the AltGr key. A keystroke is an Alt sequence
- * if an Alt key is seen that can't be an AltGr (since an AltGr sequence
- * could be a character, and in some layouts it could even be an ASCII
- * character). This recognition is different on NT-based and 95-based
- * Windows:
- *
- * * On NT-based Windows, AltGr signals as right Alt and left Ctrl
- * together. So an Alt sequence is recognized if either Alt key is
- * pressed and if right Alt and left Ctrl are not both present. This
- * is true even if the keyboard in use does not have an AltGr key, and
- * uses right Alt for AltGr.
- *
- * * On 95-based Windows, with a keyboard that lacks the AltGr key, the
- * right Alt key is used instead. But it still signals as right Alt,
- * without left Ctrl. There is no way for the application to know
- * whether right Alt is Alt or AltGr, and so it is always assumed
- * to be AltGr. This means that Alt sequences must be formed with
- * left Alt.
- *
- * So the patch processes keystrokes as follows:
- *
- * * If the scan and virtual key codes are both 0, it's the bogus key,
- * and we ignore it.
- *
- * * Keys on the numeric keypad are processed for commands as in the
- * unpatched Nethack, and for prompts by returning the ASCII
- * character, even if the num lock is off.
- *
- * * Alt sequences are processed for commands as in the unpatched
- * Nethack, and ignored for prompts.
- *
- * * Control codes are returned as received, because ReadConsole will
- * not return the ESC key.
- *
- * * Other key-down events are passed to ReadConsole. The use of
- * ReadConsole is different for commands than for prompts:
- *
- * o For commands, the bogus key is pushed onto the queue before
- * ReadConsole is called. On return, non-ASCII characters are
- * filtered, so they are not mistaken for Alt sequences; this also
- * filters the bogus key.
- *
- * o For prompts, the bogus key is not used, because that would
- * interfere with dead keys. Eight bit characters may be returned,
- * and are coded in the configured code page.
- *
- *
- * Possible improvements
- * =====================
- *
- * Some possible improvements remain:
- *
- * * Integrate the existing Finnish keyboard patch, for use with non-
- * QWERTY layouts such as the German QWERTZ keyboard or Dvorak.
- *
- * * Fix the keyboard glitches in the graphical version. Namely, dead
- * keys don't work, and input comes in as ISO-8859-1 but is displayed
- * as code page 437 if IBMgraphics is set on startup.
- *
- * * Transform incoming text to ISO-8859-1, for full compatibility with
- * the graphical version.
- *
- * * After pushing the bogus key and calling ReadConsole, check to see
- * if we got the bogus key; if so, and an Alt is pressed, process the
- * event as an Alt sequence.
- *
- */
-
-static char where_to_get_source[] = "http://www.nethack.org/";
-static char author[] = "Ray Chason";
-
-#include "win32api.h"
-#include "hack.h"
-#include "wintty.h"
-
-extern HANDLE hConIn;
-extern INPUT_RECORD ir;
-char dllname[512];
-char *shortdllname;
-
-int FDECL(__declspec(dllexport) __stdcall ProcessKeystroke,
- (HANDLE hConIn, INPUT_RECORD *ir, boolean *valid,
- BOOLEAN_P numberpad, int portdebug));
-
-static INPUT_RECORD bogus_key;
-
-int WINAPI
-DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
-{
- char dlltmpname[512];
- char *tmp = dlltmpname, *tmp2;
- *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0';
- (void) strcpy(dllname, tmp);
- tmp2 = strrchr(dllname, '\\');
- if (tmp2) {
- tmp2++;
- shortdllname = tmp2;
- }
- /* A bogus key that will be filtered when received, to keep ReadConsole
- * from blocking */
- bogus_key.EventType = KEY_EVENT;
- bogus_key.Event.KeyEvent.bKeyDown = 1;
- bogus_key.Event.KeyEvent.wRepeatCount = 1;
- bogus_key.Event.KeyEvent.wVirtualKeyCode = 0;
- bogus_key.Event.KeyEvent.wVirtualScanCode = 0;
- bogus_key.Event.KeyEvent.uChar.AsciiChar = (uchar) 0x80;
- bogus_key.Event.KeyEvent.dwControlKeyState = 0;
- return TRUE;
-}
-
-/*
- * Keyboard translation tables.
- * (Adopted from the MSDOS port)
- */
-
-#define KEYPADLO 0x47
-#define KEYPADHI 0x53
-
-#define PADKEYS (KEYPADHI - KEYPADLO + 1)
-#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
-#define isnumkeypad(x) \
- (KEYPADLO <= (x) && (x) <= 0x51 && (x) != 0x4A && (x) != 0x4E)
-
-#ifdef QWERTZ_SUPPORT
-/* when 'numberpad' is 0 and Cmd.swap_yz is True
- (signaled by setting 0x10 on boolean numpad argument)
- treat keypress of numpad 7 as 'z' rather than 'y' */
-static boolean qwertz = FALSE;
-#endif
-
-/*
- * Keypad keys are translated to the normal values below.
- * Shifted keypad keys are translated to the
- * shift values below.
- */
-
-static const struct pad {
- uchar normal, shift, cntrl;
-} keypad[PADKEYS] =
- {
- { 'y', 'Y', C('y') }, /* 7 */
- { 'k', 'K', C('k') }, /* 8 */
- { 'u', 'U', C('u') }, /* 9 */
- { 'm', C('p'), C('p') }, /* - */
- { 'h', 'H', C('h') }, /* 4 */
- { 'g', 'G', 'g' }, /* 5 */
- { 'l', 'L', C('l') }, /* 6 */
- { '+', 'P', C('p') }, /* + */
- { 'b', 'B', C('b') }, /* 1 */
- { 'j', 'J', C('j') }, /* 2 */
- { 'n', 'N', C('n') }, /* 3 */
- { 'i', 'I', C('i') }, /* Ins */
- { '.', ':', ':' } /* Del */
- },
- numpad[PADKEYS] = {
- { '7', M('7'), '7' }, /* 7 */
- { '8', M('8'), '8' }, /* 8 */
- { '9', M('9'), '9' }, /* 9 */
- { 'm', C('p'), C('p') }, /* - */
- { '4', M('4'), '4' }, /* 4 */
- { 'g', 'G', 'g' }, /* 5 */
- { '6', M('6'), '6' }, /* 6 */
- { '+', 'P', C('p') }, /* + */
- { '1', M('1'), '1' }, /* 1 */
- { '2', M('2'), '2' }, /* 2 */
- { '3', M('3'), '3' }, /* 3 */
- { 'i', 'I', C('i') }, /* Ins */
- { '.', ':', ':' } /* Del */
- };
-
-#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
-
-/* Use process_keystroke for key commands, process_keystroke2 for prompts */
-/* int FDECL(process_keystroke, (INPUT_RECORD *ir, boolean *valid, int
- * portdebug)); */
-int FDECL(process_keystroke2, (HANDLE, INPUT_RECORD *ir, boolean *valid));
-static int FDECL(is_altseq, (unsigned long shiftstate));
-
-static int
-is_altseq(shiftstate)
-unsigned long shiftstate;
-{
- /* We need to distinguish the Alt keys from the AltGr key.
- * On NT-based Windows, AltGr signals as right Alt and left Ctrl together;
- * on 95-based Windows, AltGr signals as right Alt only.
- * So on NT, we signal Alt if either Alt is pressed and left Ctrl is not,
- * and on 95, we signal Alt for left Alt only. */
- switch (shiftstate
- & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED)) {
- case LEFT_ALT_PRESSED:
- case LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED:
- return 1;
-
- case RIGHT_ALT_PRESSED:
- case RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED:
- return (GetVersion() & 0x80000000) == 0;
-
- default:
- return 0;
- }
-}
-
-int __declspec(dllexport) __stdcall ProcessKeystroke(hConIn, ir, valid,
- numberpad, portdebug)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-boolean *valid;
-boolean numberpad;
-int portdebug;
-{
- int metaflags = 0, k = 0;
- int keycode, vk;
- unsigned char ch, pre_ch, mk = 0;
- unsigned short int scan;
- unsigned long shiftstate;
- int altseq = 0;
- const struct pad *kpad;
- DWORD count;
-
-#ifdef QWERTZ_SUPPORT
- if (numberpad & 0x10) {
- numberpad &= ~0x10;
- qwertz = TRUE;
- } else {
- qwertz = FALSE;
- }
-#endif
- shiftstate = 0L;
- ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- keycode = MapVirtualKey(vk, 2);
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
- if (scan == 0 && vk == 0) {
- /* It's the bogus_key */
- ReadConsoleInput(hConIn, ir, 1, &count);
- *valid = FALSE;
- return 0;
- }
-
- if (is_altseq(shiftstate)) {
- if (ch || inmap(keycode, vk))
- altseq = 1;
- else
- altseq = -1; /* invalid altseq */
- }
- if (ch || (iskeypad(scan)) || (altseq > 0))
- *valid = TRUE;
- /* if (!valid) return 0; */
- /*
- * shiftstate can be checked to see if various special
- * keys were pressed at the same time as the key.
- * Currently we are using the ALT & SHIFT & CONTROLS.
- *
- * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
- * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
- * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
- * CAPSLOCK_ON, ENHANCED_KEY
- *
- * are all valid bit masks to use on shiftstate.
- * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
- * left control key was pressed with the keystroke.
- */
- if (iskeypad(scan)) {
- ReadConsoleInput(hConIn, ir, 1, &count);
- kpad = numberpad ? numpad : keypad;
- if (shiftstate & SHIFT_PRESSED) {
- ch = kpad[scan - KEYPADLO].shift;
- } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
- ch = kpad[scan - KEYPADLO].cntrl;
- } else {
- ch = kpad[scan - KEYPADLO].normal;
- }
-#ifdef QWERTZ_SUPPORT
- /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting,
- 'numberpad' will be 0; core swaps y to zap, z to move northwest;
- we want numpad 7 to move northwest, so when qwertz is set,
- tell core that user who types numpad 7 typed z rather than y */
- if (qwertz && kpad[scan - KEYPADLO].normal == 'y')
- ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */
-#endif /*QWERTZ_SUPPORT*/
- } else if (altseq > 0) { /* ALT sequence */
- ReadConsoleInput(hConIn, ir, 1, &count);
- if (vk == 0xBF)
- ch = M('?');
- else
- ch = M(tolower((uchar) keycode));
- } else if (ch < 32 && !isnumkeypad(scan)) {
- /* Control code; ReadConsole seems to filter some of these,
- * including ESC */
- ReadConsoleInput(hConIn, ir, 1, &count);
- }
- /* Attempt to work better with international keyboards. */
- else {
- CHAR ch2;
- DWORD written;
- /* The bogus_key guarantees that ReadConsole will return,
- * and does not itself do anything */
- WriteConsoleInput(hConIn, &bogus_key, 1, &written);
- ReadConsole(hConIn, &ch2, 1, &count, NULL);
- /* Prevent high characters from being interpreted as alt
- * sequences; also filter the bogus_key */
- if (ch2 & 0x80)
- *valid = FALSE;
- else
- ch = ch2;
- if (ch == 0)
- *valid = FALSE;
- }
- if (ch == '\r')
- ch = '\n';
-#ifdef PORT_DEBUG
- if (portdebug) {
- char buf[BUFSZ];
- Sprintf(buf, "PORTDEBUG: ch=%u, scan=%u, vk=%d, pre=%d, "
- "shiftstate=0x%X (ESC to end)\n",
- ch, scan, vk, pre_ch, shiftstate);
- fprintf(stdout, "\n%s", buf);
- }
-#endif
- return ch;
-}
-
-int
-process_keystroke2(hConIn, ir, valid)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-boolean *valid;
-{
- /* Use these values for the numeric keypad */
- static const char keypad_nums[] = "789-456+1230.";
-
- unsigned char ch;
- int vk;
- unsigned short int scan;
- unsigned long shiftstate;
- int altseq;
- DWORD count;
-
- ch = ir->Event.KeyEvent.uChar.AsciiChar;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
-
- if (scan == 0 && vk == 0) {
- /* It's the bogus_key */
- ReadConsoleInput(hConIn, ir, 1, &count);
- *valid = FALSE;
- return 0;
- }
-
- altseq = is_altseq(shiftstate);
- if (ch || (iskeypad(scan)) || altseq)
- *valid = TRUE;
- /* if (!valid) return 0; */
- /*
- * shiftstate can be checked to see if various special
- * keys were pressed at the same time as the key.
- * Currently we are using the ALT & SHIFT & CONTROLS.
- *
- * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
- * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
- * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
- * CAPSLOCK_ON, ENHANCED_KEY
- *
- * are all valid bit masks to use on shiftstate.
- * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
- * left control key was pressed with the keystroke.
- */
- if (iskeypad(scan) && !altseq) {
- ReadConsoleInput(hConIn, ir, 1, &count);
- ch = keypad_nums[scan - KEYPADLO];
- } else if (ch < 32 && !isnumkeypad(scan)) {
- /* Control code; ReadConsole seems to filter some of these,
- * including ESC */
- ReadConsoleInput(hConIn, ir, 1, &count);
- }
- /* Attempt to work better with international keyboards. */
- else {
- CHAR ch2;
- ReadConsole(hConIn, &ch2, 1, &count, NULL);
- ch = ch2 & 0xFF;
- if (ch == 0)
- *valid = FALSE;
- }
- if (ch == '\r')
- ch = '\n';
- return ch;
-}
-
-int __declspec(dllexport) __stdcall CheckInput(hConIn, ir, count, numpad,
- mode, mod, cc)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-DWORD *count;
-int mode;
-int *mod;
-boolean numpad;
-coord *cc;
-{
-#if defined(SAFERHANGUP)
- DWORD dwWait;
-#endif
- int ch;
- boolean valid = 0, done = 0;
-
-#ifdef QWERTZ_SUPPORT
- if (numpad & 0x10) {
- numpad &= ~0x10;
- qwertz = TRUE;
- } else {
- qwertz = FALSE;
- }
-#endif
- while (!done) {
- *count = 0;
- dwWait = WaitForSingleObject(hConIn, INFINITE);
-#if defined(SAFERHANGUP)
- if (dwWait == WAIT_FAILED)
- return '\033';
-#endif
- PeekConsoleInput(hConIn, ir, 1, count);
- if (mode == 0) {
- if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
- ch = process_keystroke2(hConIn, ir, &valid);
- done = valid;
- } else
- ReadConsoleInput(hConIn, ir, 1, count);
- } else {
- ch = 0;
- if (count > 0) {
- if (ir->EventType == KEY_EVENT
- && ir->Event.KeyEvent.bKeyDown) {
-#ifdef QWERTZ_SUPPORT
- if (qwertz)
- numpad |= 0x10;
-#endif
- ch = ProcessKeystroke(hConIn, ir, &valid, numpad,
-#ifdef PORTDEBUG
- 1);
-#else
- 0);
-#endif
-#ifdef QWERTZ_SUPPORT
- numpad &= ~0x10;
-#endif
- if (valid)
- return ch;
- } else {
- ReadConsoleInput(hConIn, ir, 1, count);
- if (ir->EventType == MOUSE_EVENT) {
- if ((ir->Event.MouseEvent.dwEventFlags == 0)
- && (ir->Event.MouseEvent.dwButtonState
- & MOUSEMASK)) {
- cc->x =
- ir->Event.MouseEvent.dwMousePosition.X + 1;
- cc->y =
- ir->Event.MouseEvent.dwMousePosition.Y - 1;
-
- if (ir->Event.MouseEvent.dwButtonState
- & LEFTBUTTON)
- *mod = CLICK_1;
- else if (ir->Event.MouseEvent.dwButtonState
- & RIGHTBUTTON)
- *mod = CLICK_2;
-#if 0 /* middle button */
- else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
- *mod = CLICK_3;
-#endif
- return 0;
- }
- }
-#if 0
- /* We ignore these types of console events */
- else if (ir->EventType == FOCUS_EVENT) {
- }
- else if (ir->EventType == MENU_EVENT) {
- }
-#endif
- }
- } else
- done = 1;
- }
- }
- *mod = 0;
- return ch;
-}
-
-int __declspec(dllexport) __stdcall NHkbhit(hConIn, ir)
-HANDLE hConIn;
-INPUT_RECORD *ir;
-{
- int done = 0; /* true = "stop searching" */
- int retval; /* true = "we had a match" */
- DWORD count;
- unsigned short int scan;
- unsigned char ch;
- unsigned long shiftstate;
- int altseq = 0, keycode, vk;
-
- done = 0;
- retval = 0;
- while (!done) {
- count = 0;
- PeekConsoleInput(hConIn, ir, 1, &count);
- if (count > 0) {
- if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
- ch = ir->Event.KeyEvent.uChar.AsciiChar;
- scan = ir->Event.KeyEvent.wVirtualScanCode;
- shiftstate = ir->Event.KeyEvent.dwControlKeyState;
- vk = ir->Event.KeyEvent.wVirtualKeyCode;
- if (scan == 0 && vk == 0) {
- /* It's the bogus_key. Discard it */
- ReadConsoleInput(hConIn,ir,1,&count);
- } else {
- keycode = MapVirtualKey(vk, 2);
- if (is_altseq(shiftstate)) {
- if (ch || inmap(keycode, vk))
- altseq = 1;
- else
- altseq = -1; /* invalid altseq */
- }
- if (ch || iskeypad(scan) || altseq) {
- done = 1; /* Stop looking */
- retval = 1; /* Found what we sought */
- } else {
- /* Strange Key event; let's purge it to avoid trouble */
- ReadConsoleInput(hConIn, ir, 1, &count);
- }
- }
-
- } else if ((ir->EventType == MOUSE_EVENT
- && (ir->Event.MouseEvent.dwButtonState
- & MOUSEMASK))) {
- done = 1;
- retval = 1;
- }
-
- else /* Discard it, it's an insignificant event */
- ReadConsoleInput(hConIn, ir, 1, &count);
- } else /* There are no events in console event queue */ {
- done = 1; /* Stop looking */
- retval = 0;
- }
- }
- return retval;
-}
-
-int __declspec(dllexport) __stdcall SourceWhere(buf)
-char **buf;
-{
- if (!buf)
- return 0;
- *buf = where_to_get_source;
- return 1;
-}
-
-int __declspec(dllexport) __stdcall SourceAuthor(buf)
-char **buf;
-{
- if (!buf)
- return 0;
- *buf = author;
- return 1;
-}
-
-int __declspec(dllexport) __stdcall KeyHandlerName(buf, full)
-char **buf;
-int full;
-{
- if (!buf)
- return 0;
- if (full)
- *buf = dllname;
- else
- *buf = shortdllname;
- return 1;
-}
diff --git a/sys/winnt/nttty.c b/sys/winnt/nttty.c
index c0c94fb24c..504dcc00ea 100644
--- a/sys/winnt/nttty.c
+++ b/sys/winnt/nttty.c
@@ -8,8 +8,8 @@
* Initial Creation M. Allison 1993/01/31
* Switch to low level console output routines M. Allison 2003/10/01
* Restrict cursor movement until input pending M. Lehotay 2003/10/02
- * Call Unicode version of output API on NT R. Chason 2005/10/28
- * Use of back buffer to improve performance B. House 2018/05/06
+ * Call Unicode version of output API on NT R. Chason 2005/10/28
+ * Use of back buffer to improve performance B. House 2018/05/06
*
*/
@@ -179,33 +179,36 @@ static char nullstr[] = "";
char erase_char, kill_char;
#define DEFTEXTCOLOR ttycolors[7]
-/* dynamic keystroke handling .DLL support */
-typedef int(__stdcall *PROCESS_KEYSTROKE)(HANDLE, INPUT_RECORD *, boolean *,
- BOOLEAN_P, int);
-
-typedef int(__stdcall *NHKBHIT)(HANDLE, INPUT_RECORD *);
-
-typedef int(__stdcall *CHECKINPUT)(HANDLE, INPUT_RECORD *, DWORD *, BOOLEAN_P,
+int default_processkeystroke(HANDLE, INPUT_RECORD *, boolean *, boolean, int);
+int default_kbhit(HANDLE, INPUT_RECORD *);
+int default_checkinput(HANDLE, INPUT_RECORD *, DWORD *, boolean,
+ int, int *, coord *);
+
+int ray_processkeystroke(HANDLE, INPUT_RECORD *, boolean *, boolean, int);
+int ray_kbhit(HANDLE, INPUT_RECORD *);
+int ray_checkinput(HANDLE, INPUT_RECORD *, DWORD *, boolean,
+ int, int *, coord *);
+
+int nh340_processkeystroke(HANDLE, INPUT_RECORD *, boolean *, boolean, int);
+int nh340_kbhit(HANDLE, INPUT_RECORD *);
+int nh340_checkinput(HANDLE, INPUT_RECORD *, DWORD *, boolean,
+ int, int *, coord *);
+
+struct keyboard_handling_t {
+ char *pKeyHandlingName;
+ int (*pProcessKeystroke)(HANDLE, INPUT_RECORD *, boolean *,
+ boolean, int);
+ int (*pNHkbhit)(HANDLE, INPUT_RECORD *);
+ int (*pCheckInput)(HANDLE, INPUT_RECORD *, DWORD *, boolean,
int, int *, coord *);
+} keyboard_handling = {
+ (char *) no_keyhandling,
+ default_processkeystroke,
+ default_kbhit,
+ default_checkinput
+};
-typedef int(__stdcall *SOURCEWHERE)(char **);
-
-typedef int(__stdcall *SOURCEAUTHOR)(char **);
-
-typedef int(__stdcall *KEYHANDLERNAME)(char **, int);
-
-typedef struct {
- char * name; // name without DLL extension
- HANDLE hLibrary;
- PROCESS_KEYSTROKE pProcessKeystroke;
- NHKBHIT pNHkbhit;
- CHECKINPUT pCheckInput;
- SOURCEWHERE pSourceWhere;
- SOURCEAUTHOR pSourceAuthor;
- KEYHANDLERNAME pKeyHandlerName;
-} keyboard_handler_t;
-
-keyboard_handler_t keyboard_handler;
+static INPUT_RECORD bogus_key;
/* Console buffer flipping support */
@@ -244,7 +247,7 @@ static void back_buffer_flip()
void buffer_fill_to_end(cell_t * buffer, cell_t * fill, int x, int y)
{
nhassert(x >= 0 && x < console.width);
- nhassert(y >= 0 && ((y < console.height) || (y == console.height &&
+ nhassert(y >= 0 && ((y < console.height) || (y == console.height &&
x == 0)));
cell_t * dst = buffer + console.width * y + x;
@@ -259,7 +262,7 @@ void buffer_fill_to_end(cell_t * buffer, cell_t * fill, int x, int y)
static void buffer_clear_to_end_of_line(cell_t * buffer, int x, int y)
{
nhassert(x >= 0 && x < console.width);
- nhassert(y >= 0 && ((y < console.height) || (y == console.height &&
+ nhassert(y >= 0 && ((y < console.height) || (y == console.height &&
x == 0)));
cell_t * dst = buffer + console.width * y + x;
cell_t *sentinel = buffer + console.width * (y + 1);
@@ -433,7 +436,7 @@ int portdebug;
if (Cmd.swap_yz)
numberpad |= 0x10;
#endif
- ch = keyboard_handler.pProcessKeystroke(
+ ch = keyboard_handling.pProcessKeystroke(
console.hConIn, ir, valid, numberpad, portdebug);
#ifdef QWERTZ_SUPPORT
numberpad &= ~0x10;
@@ -447,7 +450,7 @@ int portdebug;
int
nttty_kbhit()
{
- return keyboard_handler.pNHkbhit(console.hConIn, &ir);
+ return keyboard_handling.pNHkbhit(console.hConIn, &ir);
}
int
@@ -468,7 +471,7 @@ tgetch()
return (program_state.done_hup)
? '\033'
- : keyboard_handler.pCheckInput(
+ : keyboard_handling.pCheckInput(
console.hConIn, &ir, &count, numpad, 0, &mod, &cc);
}
@@ -490,7 +493,7 @@ int *x, *y, *mod;
#endif
ch = (program_state.done_hup)
? '\033'
- : keyboard_handler.pCheckInput(
+ : keyboard_handling.pCheckInput(
console.hConIn, &ir, &count, numpad, 1, mod, &cc);
#ifdef QWERTZ_SUPPORT
numpad &= ~0x10;
@@ -710,7 +713,7 @@ raw_clear_screen()
void
clear_screen()
{
- buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
+ buffer_fill_to_end(console.back_buffer, &clear_cell, 0, 0);
home();
}
@@ -994,38 +997,6 @@ win32con_debug_keystrokes()
}
(void) doredraw();
}
-void
-win32con_handler_info()
-{
- char *buf;
- int ci;
- if (!keyboard_handler.pSourceAuthor && !keyboard_handler.pSourceWhere)
- pline("Keyboard handler source info and author unavailable.");
- else {
- if (keyboard_handler.pKeyHandlerName &&
- keyboard_handler.pKeyHandlerName(&buf, 1)) {
- xputs("\n");
- xputs("Keystroke handler loaded: \n ");
- xputs(buf);
- }
- if (keyboard_handler.pSourceAuthor &&
- keyboard_handler.pSourceAuthor(&buf)) {
- xputs("\n");
- xputs("Keystroke handler Author: \n ");
- xputs(buf);
- }
- if (keyboard_handler.pSourceWhere &&
- keyboard_handler.pSourceWhere(&buf)) {
- xputs("\n");
- xputs("Keystroke handler source code available at:\n ");
- xputs(buf);
- }
- xputs("\nPress any key to resume.");
- ci = nhgetch();
- (void) doredraw();
- }
-}
-
void
win32con_toggle_cursor_info()
{
@@ -1067,81 +1038,6 @@ register char *op;
key_overrides[idx] = val;
}
-void unload_keyboard_handler()
-{
- nhassert(keyboard_handler.hLibrary != NULL);
-
- FreeLibrary(keyboard_handler.hLibrary);
- memset(&keyboard_handler, 0, sizeof(keyboard_handler_t));
-}
-
-boolean
-load_keyboard_handler(const char * inName)
-{
- char path[MAX_ALTKEYHANDLER + 4];
- strcpy(path, inName);
- strcat(path, ".dll");
-
- HANDLE hLibrary = LoadLibrary(path);
-
- if (hLibrary == NULL)
- return FALSE;
-
- PROCESS_KEYSTROKE pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress(
- hLibrary, TEXT("ProcessKeystroke"));
- NHKBHIT pNHkbhit = (NHKBHIT) GetProcAddress(
- hLibrary, TEXT("NHkbhit"));
- CHECKINPUT pCheckInput =
- (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput"));
-
- if (!pProcessKeystroke || !pNHkbhit || !pCheckInput)
- {
- return FALSE;
- } else {
- if (keyboard_handler.hLibrary != NULL)
- unload_keyboard_handler();
-
- keyboard_handler.hLibrary = hLibrary;
-
- keyboard_handler.pProcessKeystroke = pProcessKeystroke;
- keyboard_handler.pNHkbhit = pNHkbhit;
- keyboard_handler.pCheckInput = pCheckInput;
-
- keyboard_handler.pSourceWhere =
- (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere"));
- keyboard_handler.pSourceAuthor =
- (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor"));
- keyboard_handler.pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress(
- hLibrary, TEXT("KeyHandlerName"));
- }
-
- return TRUE;
-}
-
-void set_altkeyhandler(const char * inName)
-{
- if (strlen(inName) >= MAX_ALTKEYHANDLER) {
- config_error_add("altkeyhandler name '%s' is too long", inName);
- return;
- }
-
- char name[MAX_ALTKEYHANDLER];
- strcpy(name, inName);
-
- /* We support caller mistakenly giving name with '.dll' extension */
- char * ext = strchr(name, '.');
- if (ext != NULL) *ext = '\0';
-
- if (load_keyboard_handler(name))
- strcpy(iflags.altkeyhandler, name);
- else {
- config_error_add("unable to load altkeyhandler '%s'", name);
- return;
- }
-
- return;
-}
-
/* fatal error */
/*VARARGS1*/
@@ -1759,7 +1655,7 @@ void set_cp_map()
// code page 437 mappings.
if (console.cpMap[i] < 32)
console.cpMap[i] = cp437[console.cpMap[i]];
- }
+ }
}
}
@@ -1952,13 +1848,11 @@ void nethack_enter_nttty()
/* This was overriding the handler that had already
been loaded during options parsing. Needs to
check first */
- if (!iflags.altkeyhandler[0]) {
+ if (iflags.key_handling == no_keyhandling) {
if (primary_language == LANG_ENGLISH) {
- if (!load_keyboard_handler("nhdefkey"))
- error("Unable to load nhdefkey.dll");
+ set_altkeyhandling("default");
} else {
- if (!load_keyboard_handler("nhraykey"))
- error("Unable to load nhraykey.dll");
+ set_altkeyhandling("ray");
}
}
}
@@ -2001,4 +1895,1271 @@ VA_DECL(const char *, fmt)
return;
}
+
+/*
+ * Keyboard translation tables.
+ * (Adopted from the MSDOS port)
+ */
+
+#define KEYPADLO 0x47
+#define KEYPADHI 0x53
+
+#define PADKEYS (KEYPADHI - KEYPADLO + 1)
+#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
+#define isnumkeypad(x) \
+ (KEYPADLO <= (x) && (x) <= 0x51 && (x) != 0x4A && (x) != 0x4E)
+
+#ifdef QWERTZ_SUPPORT
+/* when 'numberpad' is 0 and Cmd.swap_yz is True
+ (signaled by setting 0x10 on boolean numpad argument)
+ treat keypress of numpad 7 as 'z' rather than 'y' */
+static boolean qwertz = FALSE;
+#endif
+#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
+
+struct pad {
+ uchar normal, shift, cntrl;
+};
+
+/*
+ * default key handling
+ *
+ * This is the default NetHack keystroke processing.
+ * Use the .nethackrc "altkeyhandling" option to set a
+ * different handling type.
+ *
+ */
+/*
+ * Keypad keys are translated to the normal values below.
+ * Shifted keypad keys are translated to the
+ * shift values below.
+ */
+
+static const struct pad default_keypad[PADKEYS] = {
+ { 'y', 'Y', C('y') }, /* 7 */
+ { 'k', 'K', C('k') }, /* 8 */
+ { 'u', 'U', C('u') }, /* 9 */
+ { 'm', C('p'), C('p') }, /* - */
+ { 'h', 'H', C('h') }, /* 4 */
+ { 'g', 'G', 'g' }, /* 5 */
+ { 'l', 'L', C('l') }, /* 6 */
+ { '+', 'P', C('p') }, /* + */
+ { 'b', 'B', C('b') }, /* 1 */
+ { 'j', 'J', C('j') }, /* 2 */
+ { 'n', 'N', C('n') }, /* 3 */
+ { 'i', 'I', C('i') }, /* Ins */
+ { '.', ':', ':' } /* Del */
+}, default_numpad[PADKEYS] = {
+ { '7', M('7'), '7' }, /* 7 */
+ { '8', M('8'), '8' }, /* 8 */
+ { '9', M('9'), '9' }, /* 9 */
+ { 'm', C('p'), C('p') }, /* - */
+ { '4', M('4'), '4' }, /* 4 */
+ { '5', M('5'), '5' }, /* 5 */
+ { '6', M('6'), '6' }, /* 6 */
+ { '+', 'P', C('p') }, /* + */
+ { '1', M('1'), '1' }, /* 1 */
+ { '2', M('2'), '2' }, /* 2 */
+ { '3', M('3'), '3' }, /* 3 */
+ { '0', M('0'), '0' }, /* Ins */
+ { '.', ':', ':' } /* Del */
+};
+
+/*
+ * Keypad keys are translated to the normal values below.
+ * Shifted keypad keys are translated to the
+ * shift values below.
+ */
+
+static const struct pad
+ray_keypad[PADKEYS] = {
+ { 'y', 'Y', C('y') }, /* 7 */
+ { 'k', 'K', C('k') }, /* 8 */
+ { 'u', 'U', C('u') }, /* 9 */
+ { 'm', C('p'), C('p') }, /* - */
+ { 'h', 'H', C('h') }, /* 4 */
+ { 'g', 'G', 'g' }, /* 5 */
+ { 'l', 'L', C('l') }, /* 6 */
+ { '+', 'P', C('p') }, /* + */
+ { 'b', 'B', C('b') }, /* 1 */
+ { 'j', 'J', C('j') }, /* 2 */
+ { 'n', 'N', C('n') }, /* 3 */
+ { 'i', 'I', C('i') }, /* Ins */
+ { '.', ':', ':' } /* Del */
+},
+ray_numpad[PADKEYS] = {
+ { '7', M('7'), '7' }, /* 7 */
+ { '8', M('8'), '8' }, /* 8 */
+ { '9', M('9'), '9' }, /* 9 */
+ { 'm', C('p'), C('p') }, /* - */
+ { '4', M('4'), '4' }, /* 4 */
+ { 'g', 'G', 'g' }, /* 5 */
+ { '6', M('6'), '6' }, /* 6 */
+ { '+', 'P', C('p') }, /* + */
+ { '1', M('1'), '1' }, /* 1 */
+ { '2', M('2'), '2' }, /* 2 */
+ { '3', M('3'), '3' }, /* 3 */
+ { 'i', 'I', C('i') }, /* Ins */
+ { '.', ':', ':' } /* Del */
+};
+
+static const struct pad
+nh340_keypad[PADKEYS] = {
+ { 'y', 'Y', C('y') }, /* 7 */
+ { 'k', 'K', C('k') }, /* 8 */
+ { 'u', 'U', C('u') }, /* 9 */
+ { 'm', C('p'), C('p') }, /* - */
+ { 'h', 'H', C('h') }, /* 4 */
+ { 'g', 'G', 'g' }, /* 5 */
+ { 'l', 'L', C('l') }, /* 6 */
+ { '+', 'P', C('p') }, /* + */
+ { 'b', 'B', C('b') }, /* 1 */
+ { 'j', 'J', C('j') }, /* 2 */
+ { 'n', 'N', C('n') }, /* 3 */
+ { 'i', 'I', C('i') }, /* Ins */
+ { '.', ':', ':' } /* Del */
+},
+nh340_numpad[PADKEYS] = {
+ { '7', M('7'), '7' }, /* 7 */
+ { '8', M('8'), '8' }, /* 8 */
+ { '9', M('9'), '9' }, /* 9 */
+ { 'm', C('p'), C('p') }, /* - */
+ { '4', M('4'), '4' }, /* 4 */
+ { 'g', 'G', 'g' }, /* 5 */
+ { '6', M('6'), '6' }, /* 6 */
+ { '+', 'P', C('p') }, /* + */
+ { '1', M('1'), '1' }, /* 1 */
+ { '2', M('2'), '2' }, /* 2 */
+ { '3', M('3'), '3' }, /* 3 */
+ { 'i', 'I', C('i') }, /* Ins */
+ { '.', ':', ':' } /* Del */
+};
+
+static struct pad keypad[PADKEYS], numpad[PADKEYS];
+static BYTE KeyState[256];
+static const char default_name[] = "default";
+const char *const legal_key_handling[] = {
+ "none",
+ "default",
+ "ray",
+ "340",
+};
+enum windows_key_handling keyh[] = { no_keyhandling, default_keyhandling, ray_keyhandling,
+ nh340_keyhandling };
+
+void set_altkeyhandling(const char *inName)
+{
+ int i, k;
+ /*backward compatibility - so people's existing config files
+ may work as is */
+ if (!strcmpi(inName, "nhraykey.dll"))
+ inName = legal_key_handling[ray_keyhandling];
+ else if (!strcmpi(inName, "nh340key.dll"))
+ inName = legal_key_handling[nh340_keyhandling];
+ else if (!strcmpi(inName, "nhdefkey.dll"))
+ inName = legal_key_handling[default_keyhandling];
+
+ for (i = default_keyhandling; i < SIZE(legal_key_handling); i++) {
+ if (!strcmpi(inName, legal_key_handling[i])) {
+ iflags.key_handling = keyh[i];
+ if (keyboard_handling.pKeyHandlingName) {
+ free((genericptr_t) keyboard_handling.pKeyHandlingName);
+ keyboard_handling.pKeyHandlingName = (char *) 0;
+ }
+ switch(iflags.key_handling) {
+ case ray_keyhandling:
+ keyboard_handling.pKeyHandlingName = strdup("ray");
+ keyboard_handling.pProcessKeystroke = ray_processkeystroke;
+ keyboard_handling.pNHkbhit = ray_kbhit;
+ keyboard_handling.pCheckInput = ray_checkinput;
+ /* A bogus key that will be filtered when received, to keep ReadConsole
+ * from blocking */
+ bogus_key.EventType = KEY_EVENT;
+ bogus_key.Event.KeyEvent.bKeyDown = 1;
+ bogus_key.Event.KeyEvent.wRepeatCount = 1;
+ bogus_key.Event.KeyEvent.wVirtualKeyCode = 0;
+ bogus_key.Event.KeyEvent.wVirtualScanCode = 0;
+ bogus_key.Event.KeyEvent.uChar.AsciiChar = (uchar) 0x80;
+ bogus_key.Event.KeyEvent.dwControlKeyState = 0;
+ for (k = 0; k < SIZE(keypad); ++k) {
+ keypad[k] = ray_keypad[k];
+ numpad[k] = ray_numpad[k];
+ }
+ break;
+ case nh340_keyhandling:
+ keyboard_handling.pKeyHandlingName = strdup("340");
+ keyboard_handling.pProcessKeystroke = nh340_processkeystroke;
+ keyboard_handling.pNHkbhit = nh340_kbhit;
+ keyboard_handling.pCheckInput = nh340_checkinput;
+ for (k = 0; k < SIZE(keypad); ++k) {
+ keypad[k] = nh340_keypad[k];
+ numpad[k] = nh340_numpad[k];
+ }
+ break;
+ case default_keyhandling:
+ default:
+ keyboard_handling.pKeyHandlingName = strdup("default");
+ keyboard_handling.pProcessKeystroke
+ = default_processkeystroke;
+ keyboard_handling.pNHkbhit = default_kbhit;
+ keyboard_handling.pCheckInput = default_checkinput;
+ for (k = 0; k < SIZE(keypad); ++k) {
+ keypad[k] = default_keypad[k];
+ numpad[k] = default_numpad[k];
+ }
+ break;
+ }
+ return;
+ }
+ }
+ config_error_add("invalid altkeyhandling '%s'", inName);
+ return;
+}
+
+int
+set_keyhandling_via_option(void)
+{
+ winid tmpwin;
+ anything any;
+ int i;
+ menu_item *console_key_handling_pick = (menu_item *) 0;
+
+ tmpwin = create_nhwindow(NHW_MENU);
+ start_menu(tmpwin);
+ any = zeroany;
+ for (i = default_keyhandling; i < SIZE(legal_key_handling); i++) {
+ any.a_int = i + 1;
+ add_menu(tmpwin, 0, &any, 'a' + i,
+ 0, ATR_NONE,
+ legal_key_handling[i], 0);
+ }
+ end_menu(tmpwin, "Select windows console key handling:");
+ if (select_menu(tmpwin, PICK_ONE, &console_key_handling_pick) > 0) {
+ iflags.key_handling = keyh[console_key_handling_pick->item.a_int - 1];
+ free((genericptr_t) console_key_handling_pick);
+ }
+ destroy_nhwindow(tmpwin);
+ set_altkeyhandling(legal_key_handling[iflags.key_handling]);
+ return 1; /* optn_ok */
+}
+
+int
+default_processkeystroke(
+ HANDLE hConIn,
+ INPUT_RECORD* ir,
+ boolean* valid,
+ boolean numberpad,
+ int portdebug)
+{
+ int k = 0;
+ int keycode, vk;
+ unsigned char ch, pre_ch;
+ unsigned short int scan;
+ unsigned long shiftstate;
+ int altseq = 0;
+ const struct pad *kpad;
+
+#ifdef QWERTZ_SUPPORT
+ if (numberpad & 0x10) {
+ numberpad &= ~0x10;
+ qwertz = TRUE;
+ } else {
+ qwertz = FALSE;
+ }
+#endif
+ shiftstate = 0L;
+ ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ keycode = MapVirtualKey(vk, 2);
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+ KeyState[VK_SHIFT] = (shiftstate & SHIFT_PRESSED) ? 0x81 : 0;
+ KeyState[VK_CONTROL] =
+ (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ? 0x81 : 0;
+ KeyState[VK_CAPITAL] = (shiftstate & CAPSLOCK_ON) ? 0x81 : 0;
+
+ if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
+ if (ch || inmap(keycode, vk))
+ altseq = 1;
+ else
+ altseq = -1; /* invalid altseq */
+ }
+ if (ch || (iskeypad(scan)) || (altseq > 0))
+ *valid = TRUE;
+ /* if (!valid) return 0; */
+ /*
+ * shiftstate can be checked to see if various special
+ * keys were pressed at the same time as the key.
+ * Currently we are using the ALT & SHIFT & CONTROLS.
+ *
+ * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
+ * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
+ * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
+ * CAPSLOCK_ON, ENHANCED_KEY
+ *
+ * are all valid bit masks to use on shiftstate.
+ * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
+ * left control key was pressed with the keystroke.
+ */
+ if (iskeypad(scan)) {
+ kpad = numberpad ? numpad : keypad;
+ if (shiftstate & SHIFT_PRESSED) {
+ ch = kpad[scan - KEYPADLO].shift;
+ } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
+ ch = kpad[scan - KEYPADLO].cntrl;
+ } else {
+ ch = kpad[scan - KEYPADLO].normal;
+ }
+#ifdef QWERTZ_SUPPORT
+ /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting,
+ 'numberpad' will be 0; core swaps y to zap, z to move northwest;
+ we want numpad 7 to move northwest, so when qwertz is set,
+ tell core that user who types numpad 7 typed z rather than y */
+ if (qwertz && kpad[scan - KEYPADLO].normal == 'y')
+ ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */
+#endif /*QWERTZ_SUPPORT*/
+ } else if (altseq > 0) { /* ALT sequence */
+ if (vk == 0xBF)
+ ch = M('?');
+ else
+ ch = M(tolower((uchar) keycode));
+ }
+ /* Attempt to work better with international keyboards. */
+ else {
+ WORD chr[2];
+ k = ToAscii(vk, scan, KeyState, chr, 0);
+ if (k <= 2)
+ switch (k) {
+ case 2: /* two characters */
+ ch = (unsigned char) chr[1];
+ *valid = TRUE;
+ break;
+ case 1: /* one character */
+ ch = (unsigned char) chr[0];
+ *valid = TRUE;
+ break;
+ case 0: /* no translation */
+ default: /* negative */
+ *valid = FALSE;
+ }
+ }
+ if (ch == '\r')
+ ch = '\n';
+#ifdef PORT_DEBUG
+ if (portdebug) {
+ char buf[BUFSZ];
+ Sprintf(buf, "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, pre=%d, sh=0x%lX, "
+ "ta=%d (ESC to end)",
+ "default", ch, scan, vk, pre_ch, shiftstate, k);
+ fprintf(stdout, "\n%s", buf);
+ }
+#endif
+ return ch;
+}
+
+int
+default_kbhit(HANDLE hConIn, INPUT_RECORD *ir)
+{
+ int done = 0; /* true = "stop searching" */
+ int retval; /* true = "we had a match" */
+ DWORD count;
+ unsigned short int scan;
+ unsigned char ch;
+ unsigned long shiftstate;
+ int altseq = 0, keycode, vk;
+ done = 0;
+ retval = 0;
+ while (!done) {
+ count = 0;
+ PeekConsoleInput(hConIn, ir, 1, &count);
+ if (count > 0) {
+ if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
+ ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ keycode = MapVirtualKey(vk, 2);
+ if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
+ if (ch || inmap(keycode, vk))
+ altseq = 1;
+ else
+ altseq = -1; /* invalid altseq */
+ }
+ if (ch || iskeypad(scan) || altseq) {
+ done = 1; /* Stop looking */
+ retval = 1; /* Found what we sought */
+ } else {
+ /* Strange Key event; let's purge it to avoid trouble */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ }
+
+ } else if ((ir->EventType == MOUSE_EVENT
+ && (ir->Event.MouseEvent.dwButtonState
+ & MOUSEMASK))) {
+ done = 1;
+ retval = 1;
+ }
+
+ else /* Discard it, it's an insignificant event */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ } else /* There are no events in console event queue */ {
+ done = 1; /* Stop looking */
+ retval = 0;
+ }
+ }
+ return retval;
+}
+
+int
+default_checkinput(
+ HANDLE hConIn,
+ INPUT_RECORD *ir,
+ DWORD* count,
+ boolean numpad,
+ int mode,
+ int *mod,
+ coord *cc)
+{
+#if defined(SAFERHANGUP)
+ DWORD dwWait;
+#endif
+ int ch = 0;
+ boolean valid = 0, done = 0;
+
+#ifdef QWERTZ_SUPPORT
+ if (numpad & 0x10) {
+ numpad &= ~0x10;
+ qwertz = TRUE;
+ } else {
+ qwertz = FALSE;
+ }
+#endif
+ while (!done) {
+#if defined(SAFERHANGUP)
+ dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
+ INFINITE, // waits indefinitely
+ TRUE); // alertable wait enabled
+ if (dwWait == WAIT_FAILED)
+ return '\033';
+#endif
+ ReadConsoleInput(hConIn, ir, 1, count);
+ if (mode == 0) {
+ if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
+ ch = default_processkeystroke(hConIn, ir, &valid, numpad, 0);
+ done = valid;
+ }
+ } else {
+ if (count > 0) {
+ if (ir->EventType == KEY_EVENT
+ && ir->Event.KeyEvent.bKeyDown) {
+#ifdef QWERTZ_SUPPORT
+ if (qwertz)
+ numpad |= 0x10;
+#endif
+ ch = default_processkeystroke(hConIn, ir, &valid, numpad, 0);
+#ifdef QWERTZ_SUPPORT
+ numpad &= ~0x10;
+#endif
+ if (valid)
+ return ch;
+ } else if (ir->EventType == MOUSE_EVENT) {
+ if ((ir->Event.MouseEvent.dwEventFlags == 0)
+ && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
+ cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
+ cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
+
+ if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
+ *mod = CLICK_1;
+ else if (ir->Event.MouseEvent.dwButtonState
+ & RIGHTBUTTON)
+ *mod = CLICK_2;
+#if 0 /* middle button */
+ else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
+ *mod = CLICK_3;
+#endif
+ return 0;
+ }
+ }
+ } else
+ done = 1;
+ }
+ }
+ return mode ? 0 : ch;
+}
+
+/*
+ * Keystroke handling contributed by Ray Chason.
+ * The following text was written by Ray Chason.
+ *
+ * The problem
+ * ===========
+ *
+ * The console-mode Nethack wants both keyboard and mouse input. The
+ * problem is that the Windows API provides no easy way to get mouse input
+ * and also keyboard input properly translated according to the user's
+ * chosen keyboard layout.
+ *
+ * The ReadConsoleInput function returns a stream of keyboard and mouse
+ * events. Nethack is interested in those events that represent a key
+ * pressed, or a click on a mouse button. The keyboard events from
+ * ReadConsoleInput are not translated according to the keyboard layout,
+ * and do not take into account the shift, control, or alt keys.
+ *
+ * The PeekConsoleInput function works similarly to ReadConsoleInput,
+ * except that it does not remove an event from the queue and it returns
+ * instead of blocking when the queue is empty.
+ *
+ * A program can also use ReadConsole to get a properly translated stream
+ * of characters. Unfortunately, ReadConsole does not return mouse events,
+ * does not distinguish the keypad from the main keyboard, does not return
+ * keys shifted with Alt, and does not even return the ESC key when
+ * pressed.
+ *
+ * We want both the functionality of ReadConsole and the functionality of
+ * ReadConsoleInput. But Microsoft didn't seem to think of that.
+ *
+ *
+ * The solution, in the original code
+ * ==================================
+ *
+ * The original 3.4.1 distribution tries to get proper keyboard translation
+ * by passing keyboard events to the ToAscii function. This works, to some
+ * extent -- it takes the shift key into account, and it processes dead
+ * keys properly. But it doesn't take non-US keyboards into account. It
+ * appears that ToAscii is meant for windowed applications, and does not
+ * have enough information to do its job properly in a console application.
+ *
+ *
+ * The Finnish keyboard patch
+ * ==========================
+ *
+ * This patch adds the "subkeyvalue" option to the defaults.nh file. The
+ * user can then add OPTIONS=sukeyvalue:171/92, for instance, to replace
+ * the 171 character with 92, which is \. This works, once properly
+ * configured, but places too much burden on the user. It also bars the
+ * use of the substituted characters in naming objects or monsters.
+ *
+ *
+ * The solution presented here
+ * ===========================
+ *
+ * The best way I could find to combine the functionality of ReadConsole
+ * with that of ReadConsoleInput is simple in concept. First, call
+ * PeekConsoleInput to get the first event. If it represents a key press,
+ * call ReadConsole to retrieve the key. Otherwise, pop it off the queue
+ * with ReadConsoleInput and, if it's a mouse click, return it as such.
+ *
+ * But the Devil, as they say, is in the details. The problem is in
+ * recognizing an event that ReadConsole will return as a key. We don't
+ * want to call ReadConsole unless we know that it will immediately return:
+ * if it blocks, the mouse and the Alt sequences will cease to function
+ * until it returns.
+ *
+ * Separating process_keystroke into two functions, one for commands and a
+ * new one, process_keystroke2, for answering prompts, makes the job a lot
+ * easier. process_keystroke2 doesn't have to worry about mouse events or
+ * Alt sequences, and so the consequences are minor if ReadConsole blocks.
+ * process_keystroke, OTOH, never needs to return a non-ASCII character
+ * that was read from ReadConsole; it returns bytes with the high bit set
+ * only in response to an Alt sequence.
+ *
+ * So in process_keystroke, before calling ReadConsole, a bogus key event
+ * is pushed on the queue. This event causes ReadConsole to return, even
+ * if there was no other character available. Because the bogus key has
+ * the eighth bit set, it is filtered out. This is not done in
+ * process_keystroke2, because that would render dead keys unusable.
+ *
+ * A separate process_keystroke2 can also process the numeric keypad in a
+ * way that makes sense for prompts: just return the corresponding symbol,
+ * and pay no mind to number_pad or the num lock key.
+ *
+ * The recognition of Alt sequences is modified, to support the use of
+ * characters generated with the AltGr key. A keystroke is an Alt sequence
+ * if an Alt key is seen that can't be an AltGr (since an AltGr sequence
+ * could be a character, and in some layouts it could even be an ASCII
+ * character). This recognition is different on NT-based and 95-based
+ * Windows:
+ *
+ * * On NT-based Windows, AltGr signals as right Alt and left Ctrl
+ * together. So an Alt sequence is recognized if either Alt key is
+ * pressed and if right Alt and left Ctrl are not both present. This
+ * is true even if the keyboard in use does not have an AltGr key, and
+ * uses right Alt for AltGr.
+ *
+ * * On 95-based Windows, with a keyboard that lacks the AltGr key, the
+ * right Alt key is used instead. But it still signals as right Alt,
+ * without left Ctrl. There is no way for the application to know
+ * whether right Alt is Alt or AltGr, and so it is always assumed
+ * to be AltGr. This means that Alt sequences must be formed with
+ * left Alt.
+ *
+ * So the patch processes keystrokes as follows:
+ *
+ * * If the scan and virtual key codes are both 0, it's the bogus key,
+ * and we ignore it.
+ *
+ * * Keys on the numeric keypad are processed for commands as in the
+ * unpatched Nethack, and for prompts by returning the ASCII
+ * character, even if the num lock is off.
+ *
+ * * Alt sequences are processed for commands as in the unpatched
+ * Nethack, and ignored for prompts.
+ *
+ * * Control codes are returned as received, because ReadConsole will
+ * not return the ESC key.
+ *
+ * * Other key-down events are passed to ReadConsole. The use of
+ * ReadConsole is different for commands than for prompts:
+ *
+ * o For commands, the bogus key is pushed onto the queue before
+ * ReadConsole is called. On return, non-ASCII characters are
+ * filtered, so they are not mistaken for Alt sequences; this also
+ * filters the bogus key.
+ *
+ * o For prompts, the bogus key is not used, because that would
+ * interfere with dead keys. Eight bit characters may be returned,
+ * and are coded in the configured code page.
+ *
+ *
+ * Possible improvements
+ * =====================
+ *
+ * Some possible improvements remain:
+ *
+ * * Integrate the existing Finnish keyboard patch, for use with non-
+ * QWERTY layouts such as the German QWERTZ keyboard or Dvorak.
+ *
+ * * Fix the keyboard glitches in the graphical version. Namely, dead
+ * keys don't work, and input comes in as ISO-8859-1 but is displayed
+ * as code page 437 if IBMgraphics is set on startup.
+ *
+ * * Transform incoming text to ISO-8859-1, for full compatibility with
+ * the graphical version.
+ *
+ * * After pushing the bogus key and calling ReadConsole, check to see
+ * if we got the bogus key; if so, and an Alt is pressed, process the
+ * event as an Alt sequence.
+ *
+ */
+
+#if 0
+static char where_to_get_source[] = "http://www.nethack.org/";
+static char author[] = "Ray Chason";
+#endif
+
+int process_keystroke2(HANDLE hConIn, INPUT_RECORD *ir, boolean *valid);
+
+/* Use ray_processkeystroke for key commands, process_keystroke2 for prompts */
+/* int ray_processkeystroke(INPUT_RECORD *ir, boolean *valid, int
+ * portdebug);
+ */
+
+int process_keystroke2(HANDLE, INPUT_RECORD *ir, boolean *valid);
+static int is_altseq(unsigned long shiftstate);
+
+static int
+is_altseq(unsigned long shiftstate)
+{
+ /* We need to distinguish the Alt keys from the AltGr key.
+ * On NT-based Windows, AltGr signals as right Alt and left Ctrl together;
+ * on 95-based Windows, AltGr signals as right Alt only.
+ * So on NT, we signal Alt if either Alt is pressed and left Ctrl is not,
+ * and on 95, we signal Alt for left Alt only. */
+ switch (shiftstate
+ & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED)) {
+ case LEFT_ALT_PRESSED:
+ case LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED:
+ return 1;
+
+ case RIGHT_ALT_PRESSED:
+ case RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED:
+ return (GetVersion() & 0x80000000) == 0;
+
+ default:
+ return 0;
+ }
+}
+
+int ray_processkeystroke(
+ HANDLE hConIn,
+ INPUT_RECORD *ir,
+ boolean *valid,
+ boolean numberpad,
+ int portdebug)
+{
+ int keycode, vk;
+ unsigned char ch, pre_ch;
+ unsigned short int scan;
+ unsigned long shiftstate;
+ int altseq = 0;
+ const struct pad *kpad;
+ DWORD count;
+
+#ifdef QWERTZ_SUPPORT
+ if (numberpad & 0x10) {
+ numberpad &= ~0x10;
+ qwertz = TRUE;
+ } else {
+ qwertz = FALSE;
+ }
+#endif
+ shiftstate = 0L;
+ ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ keycode = MapVirtualKey(vk, 2);
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+ if (scan == 0 && vk == 0) {
+ /* It's the bogus_key */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ *valid = FALSE;
+ return 0;
+ }
+
+ if (is_altseq(shiftstate)) {
+ if (ch || inmap(keycode, vk))
+ altseq = 1;
+ else
+ altseq = -1; /* invalid altseq */
+ }
+ if (ch || (iskeypad(scan)) || (altseq > 0))
+ *valid = TRUE;
+ /* if (!valid) return 0; */
+ /*
+ * shiftstate can be checked to see if various special
+ * keys were pressed at the same time as the key.
+ * Currently we are using the ALT & SHIFT & CONTROLS.
+ *
+ * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
+ * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
+ * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
+ * CAPSLOCK_ON, ENHANCED_KEY
+ *
+ * are all valid bit masks to use on shiftstate.
+ * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
+ * left control key was pressed with the keystroke.
+ */
+ if (iskeypad(scan)) {
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ kpad = numberpad ? numpad : keypad;
+ if (shiftstate & SHIFT_PRESSED) {
+ ch = kpad[scan - KEYPADLO].shift;
+ } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
+ ch = kpad[scan - KEYPADLO].cntrl;
+ } else {
+ ch = kpad[scan - KEYPADLO].normal;
+ }
+#ifdef QWERTZ_SUPPORT
+ /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting,
+ 'numberpad' will be 0; core swaps y to zap, z to move northwest;
+ we want numpad 7 to move northwest, so when qwertz is set,
+ tell core that user who types numpad 7 typed z rather than y */
+ if (qwertz && kpad[scan - KEYPADLO].normal == 'y')
+ ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */
+#endif /*QWERTZ_SUPPORT*/
+ } else if (altseq > 0) { /* ALT sequence */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ if (vk == 0xBF)
+ ch = M('?');
+ else
+ ch = M(tolower((uchar) keycode));
+ } else if (ch < 32 && !isnumkeypad(scan)) {
+ /* Control code; ReadConsole seems to filter some of these,
+ * including ESC */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ }
+ /* Attempt to work better with international keyboards. */
+ else {
+ CHAR ch2;
+ DWORD written;
+ /* The bogus_key guarantees that ReadConsole will return,
+ * and does not itself do anything */
+ WriteConsoleInput(hConIn, &bogus_key, 1, &written);
+ ReadConsole(hConIn, &ch2, 1, &count, NULL);
+ /* Prevent high characters from being interpreted as alt
+ * sequences; also filter the bogus_key */
+ if (ch2 & 0x80)
+ *valid = FALSE;
+ else
+ ch = ch2;
+ if (ch == 0)
+ *valid = FALSE;
+ }
+ if (ch == '\r')
+ ch = '\n';
+#ifdef PORT_DEBUG
+ if (portdebug) {
+ char buf[BUFSZ];
+ Sprintf(buf, "PORTDEBUG: ch=%u, scan=%u, vk=%d, pre=%d, "
+ "shiftstate=0x%lX (ESC to end)\n",
+ ch, scan, vk, pre_ch, shiftstate);
+ fprintf(stdout, "\n%s", buf);
+ }
+#endif
+ return ch;
+}
+
+int
+process_keystroke2(
+ HANDLE hConIn,
+ INPUT_RECORD *ir,
+ boolean *valid)
+{
+ /* Use these values for the numeric keypad */
+ static const char keypad_nums[] = "789-456+1230.";
+
+ unsigned char ch;
+ int vk;
+ unsigned short int scan;
+ unsigned long shiftstate;
+ int altseq;
+ DWORD count;
+
+ ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+
+ if (scan == 0 && vk == 0) {
+ /* It's the bogus_key */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ *valid = FALSE;
+ return 0;
+ }
+
+ altseq = is_altseq(shiftstate);
+ if (ch || (iskeypad(scan)) || altseq)
+ *valid = TRUE;
+ /* if (!valid) return 0; */
+ /*
+ * shiftstate can be checked to see if various special
+ * keys were pressed at the same time as the key.
+ * Currently we are using the ALT & SHIFT & CONTROLS.
+ *
+ * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
+ * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
+ * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
+ * CAPSLOCK_ON, ENHANCED_KEY
+ *
+ * are all valid bit masks to use on shiftstate.
+ * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
+ * left control key was pressed with the keystroke.
+ */
+ if (iskeypad(scan) && !altseq) {
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ ch = keypad_nums[scan - KEYPADLO];
+ } else if (ch < 32 && !isnumkeypad(scan)) {
+ /* Control code; ReadConsole seems to filter some of these,
+ * including ESC */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ }
+ /* Attempt to work better with international keyboards. */
+ else {
+ CHAR ch2;
+ ReadConsole(hConIn, &ch2, 1, &count, NULL);
+ ch = ch2 & 0xFF;
+ if (ch == 0)
+ *valid = FALSE;
+ }
+ if (ch == '\r')
+ ch = '\n';
+ return ch;
+}
+
+int
+ray_checkinput(
+ HANDLE hConIn,
+ INPUT_RECORD *ir,
+ DWORD *count,
+ boolean numpad,
+ int mode,
+ int *mod,
+ coord *cc)
+{
+#if defined(SAFERHANGUP)
+ DWORD dwWait;
+#endif
+ int ch = 0;
+ boolean valid = 0, done = 0;
+
+#ifdef QWERTZ_SUPPORT
+ if (numpad & 0x10) {
+ numpad &= ~0x10;
+ qwertz = TRUE;
+ } else {
+ qwertz = FALSE;
+ }
+#endif
+ while (!done) {
+ *count = 0;
+ dwWait = WaitForSingleObject(hConIn, INFINITE);
+#if defined(SAFERHANGUP)
+ if (dwWait == WAIT_FAILED)
+ return '\033';
+#endif
+ PeekConsoleInput(hConIn, ir, 1, count);
+ if (mode == 0) {
+ if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
+ ch = process_keystroke2(hConIn, ir, &valid);
+ done = valid;
+ } else
+ ReadConsoleInput(hConIn, ir, 1, count);
+ } else {
+ ch = 0;
+ if (count > 0) {
+ if (ir->EventType == KEY_EVENT
+ && ir->Event.KeyEvent.bKeyDown) {
+#ifdef QWERTZ_SUPPORT
+ if (qwertz)
+ numpad |= 0x10;
+#endif
+ ch = ray_processkeystroke(hConIn, ir, &valid, numpad,
+#ifdef PORTDEBUG
+ 1);
+#else
+ 0);
+#endif
+#ifdef QWERTZ_SUPPORT
+ numpad &= ~0x10;
+#endif
+ if (valid)
+ return ch;
+ } else {
+ ReadConsoleInput(hConIn, ir, 1, count);
+ if (ir->EventType == MOUSE_EVENT) {
+ if ((ir->Event.MouseEvent.dwEventFlags == 0)
+ && (ir->Event.MouseEvent.dwButtonState
+ & MOUSEMASK)) {
+ cc->x =
+ ir->Event.MouseEvent.dwMousePosition.X + 1;
+ cc->y =
+ ir->Event.MouseEvent.dwMousePosition.Y - 1;
+
+ if (ir->Event.MouseEvent.dwButtonState
+ & LEFTBUTTON)
+ *mod = CLICK_1;
+ else if (ir->Event.MouseEvent.dwButtonState
+ & RIGHTBUTTON)
+ *mod = CLICK_2;
+#if 0 /* middle button */
+ else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
+ *mod = CLICK_3;
+#endif
+ return 0;
+ }
+ }
+#if 0
+ /* We ignore these types of console events */
+ else if (ir->EventType == FOCUS_EVENT) {
+ }
+ else if (ir->EventType == MENU_EVENT) {
+ }
+#endif
+ }
+ } else
+ done = 1;
+ }
+ }
+ *mod = 0;
+ return ch;
+}
+
+int
+ray_kbhit(
+ HANDLE hConIn,
+ INPUT_RECORD *ir)
+{
+ int done = 0; /* true = "stop searching" */
+ int retval; /* true = "we had a match" */
+ DWORD count;
+ unsigned short int scan;
+ unsigned char ch;
+ unsigned long shiftstate;
+ int altseq = 0, keycode, vk;
+
+ done = 0;
+ retval = 0;
+ while (!done) {
+ count = 0;
+ PeekConsoleInput(hConIn, ir, 1, &count);
+ if (count > 0) {
+ if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
+ ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ if (scan == 0 && vk == 0) {
+ /* It's the bogus_key. Discard it */
+ ReadConsoleInput(hConIn,ir,1,&count);
+ } else {
+ keycode = MapVirtualKey(vk, 2);
+ if (is_altseq(shiftstate)) {
+ if (ch || inmap(keycode, vk))
+ altseq = 1;
+ else
+ altseq = -1; /* invalid altseq */
+ }
+ if (ch || iskeypad(scan) || altseq) {
+ done = 1; /* Stop looking */
+ retval = 1; /* Found what we sought */
+ } else {
+ /* Strange Key event; let's purge it to avoid trouble */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ }
+ }
+
+ } else if ((ir->EventType == MOUSE_EVENT
+ && (ir->Event.MouseEvent.dwButtonState
+ & MOUSEMASK))) {
+ done = 1;
+ retval = 1;
+ }
+
+ else /* Discard it, it's an insignificant event */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ } else /* There are no events in console event queue */ {
+ done = 1; /* Stop looking */
+ retval = 0;
+ }
+ }
+ return retval;
+}
+
+/*
+ * nh340 key handling
+ *
+ * This is the NetHack keystroke processing from NetHack 3.4.0.
+ * It can be built as a run-time loadable dll (nh340key.dll),
+ * placed in the same directory as the nethack.exe executable,
+ * and loaded by specifying OPTIONS=altkeyhandler:nh340key
+ * in defaults.nh
+ *
+ * Keypad keys are translated to the normal values below.
+ * Shifted keypad keys are translated to the
+ * shift values below.
+ */
+
+int
+nh340_processkeystroke(
+ HANDLE hConIn,
+ INPUT_RECORD *ir,
+ boolean *valid,
+ boolean numberpad,
+ int portdebug)
+{
+ int keycode, vk;
+ unsigned char ch, pre_ch;
+ unsigned short int scan;
+ unsigned long shiftstate;
+ int altseq = 0;
+ const struct pad *kpad;
+
+#ifdef QWERTZ_SUPPORT
+ if (numberpad & 0x10) {
+ numberpad &= ~0x10;
+ qwertz = TRUE;
+ } else {
+ qwertz = FALSE;
+ }
+#endif
+
+ shiftstate = 0L;
+ ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ keycode = MapVirtualKey(vk, 2);
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+
+ if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
+ if (ch || inmap(keycode, vk))
+ altseq = 1;
+ else
+ altseq = -1; /* invalid altseq */
+ }
+ if (ch || (iskeypad(scan)) || (altseq > 0))
+ *valid = TRUE;
+ /* if (!valid) return 0; */
+ /*
+ * shiftstate can be checked to see if various special
+ * keys were pressed at the same time as the key.
+ * Currently we are using the ALT & SHIFT & CONTROLS.
+ *
+ * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
+ * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
+ * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
+ * CAPSLOCK_ON, ENHANCED_KEY
+ *
+ * are all valid bit masks to use on shiftstate.
+ * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
+ * left control key was pressed with the keystroke.
+ */
+ if (iskeypad(scan)) {
+ kpad = numberpad ? numpad : keypad;
+ if (shiftstate & SHIFT_PRESSED) {
+ ch = kpad[scan - KEYPADLO].shift;
+ } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
+ ch = kpad[scan - KEYPADLO].cntrl;
+ } else {
+ ch = kpad[scan - KEYPADLO].normal;
+ }
+#ifdef QWERTZ_SUPPORT
+ /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting,
+ 'numberpad' will be 0; core swaps y to zap, z to move northwest;
+ we want numpad 7 to move northwest, so when qwertz is set,
+ tell core that user who types numpad 7 typed z rather than y */
+ if (qwertz && kpad[scan - KEYPADLO].normal == 'y')
+ ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */
+#endif /*QWERTZ_SUPPORT*/
+ } else if (altseq > 0) { /* ALT sequence */
+ if (vk == 0xBF)
+ ch = M('?');
+ else
+ ch = M(tolower((uchar) keycode));
+ }
+ if (ch == '\r')
+ ch = '\n';
+#ifdef PORT_DEBUG
+ if (portdebug) {
+ char buf[BUFSZ];
+ Sprintf(buf,
+ "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, sh=0x%lX (ESC to end)",
+ "nh340", ch, scan, vk, shiftstate);
+ fprintf(stdout, "\n%s", buf);
+ }
+#endif
+ return ch;
+}
+
+int
+nh340_kbhit(
+ HANDLE hConIn,
+ INPUT_RECORD *ir)
+{
+ int done = 0; /* true = "stop searching" */
+ int retval; /* true = "we had a match" */
+ DWORD count;
+ unsigned short int scan;
+ unsigned char ch;
+ unsigned long shiftstate;
+ int altseq = 0, keycode, vk;
+ done = 0;
+ retval = 0;
+ while (!done) {
+ count = 0;
+ PeekConsoleInput(hConIn, ir, 1, &count);
+ if (count > 0) {
+ if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
+ ch = ir->Event.KeyEvent.uChar.AsciiChar;
+ scan = ir->Event.KeyEvent.wVirtualScanCode;
+ shiftstate = ir->Event.KeyEvent.dwControlKeyState;
+ vk = ir->Event.KeyEvent.wVirtualKeyCode;
+ keycode = MapVirtualKey(vk, 2);
+ if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
+ if (ch || inmap(keycode, vk))
+ altseq = 1;
+ else
+ altseq = -1; /* invalid altseq */
+ }
+ if (ch || iskeypad(scan) || altseq) {
+ done = 1; /* Stop looking */
+ retval = 1; /* Found what we sought */
+ } else {
+ /* Strange Key event; let's purge it to avoid trouble */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ }
+
+ } else if ((ir->EventType == MOUSE_EVENT
+ && (ir->Event.MouseEvent.dwButtonState
+ & MOUSEMASK))) {
+ done = 1;
+ retval = 1;
+ }
+
+ else /* Discard it, it's an insignificant event */
+ ReadConsoleInput(hConIn, ir, 1, &count);
+ } else /* There are no events in console event queue */ {
+ done = 1; /* Stop looking */
+ retval = 0;
+ }
+ }
+ return retval;
+}
+
+int
+nh340_checkinput(
+ HANDLE hConIn,
+ INPUT_RECORD *ir,
+ DWORD *count,
+ boolean numpad,
+ int mode,
+ int *mod,
+ coord *cc)
+{
+#if defined(SAFERHANGUP)
+ DWORD dwWait;
+#endif
+ int ch = 0;
+ boolean valid = 0, done = 0;
+
+#ifdef QWERTZ_SUPPORT
+ if (numpad & 0x10) {
+ numpad &= ~0x10;
+ qwertz = TRUE;
+ } else {
+ qwertz = FALSE;
+ }
+#endif
+ while (!done) {
+#if defined(SAFERHANGUP)
+ dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
+ INFINITE, // waits indefinitely
+ TRUE); // alertable wait enabled
+ if (dwWait == WAIT_FAILED)
+ return '\033';
+#endif
+ ReadConsoleInput(hConIn, ir, 1, count);
+ if (mode == 0) {
+ if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
+#ifdef QWERTZ_SUPPORT
+ if (qwertz)
+ numpad |= 0x10;
+#endif
+ ch = nh340_processkeystroke(hConIn, ir, &valid, numpad, 0);
+#ifdef QWERTZ_SUPPORT
+ numpad &= ~0x10;
+#endif
+ done = valid;
+ }
+ } else {
+ if (count > 0) {
+ if (ir->EventType == KEY_EVENT
+ && ir->Event.KeyEvent.bKeyDown) {
+ ch = nh340_processkeystroke(hConIn, ir, &valid, numpad, 0);
+ if (valid)
+ return ch;
+ } else if (ir->EventType == MOUSE_EVENT) {
+ if ((ir->Event.MouseEvent.dwEventFlags == 0)
+ && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
+ cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
+ cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
+
+ if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
+ *mod = CLICK_1;
+ else if (ir->Event.MouseEvent.dwButtonState
+ & RIGHTBUTTON)
+ *mod = CLICK_2;
+#if 0 /* middle button */
+ else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
+ *mod = CLICK_3;
+#endif
+ return 0;
+ }
+ }
+ } else
+ done = 1;
+ }
+ }
+ return mode ? 0 : ch;
+}
+
#endif /* WIN32 */
diff --git a/sys/winnt/stubs.c b/sys/winnt/stubs.c
index 447b0dabb0..4568a6e90a 100644
--- a/sys/winnt/stubs.c
+++ b/sys/winnt/stubs.c
@@ -10,7 +10,7 @@
#error You cannot compile this with both GUISTUB and TTYSTUB defined.
#endif
-int GUILaunched;
+extern int GUILaunched;
struct window_procs mswin_procs = { "-guistubs" };
#ifdef QT_GRAPHICS
@@ -189,4 +189,14 @@ set_altkeyhandler(const char *inName)
{
return;
}
+void
+set_altkeyhandling(const char *inName)
+{
+}
+
+int
+set_keyhandling_via_option(void)
+{
+ return 1;
+}
#endif /* TTYSTUBS */
diff --git a/sys/winnt/win10.c b/sys/winnt/win10.c
index abf76d9ebc..9791bbec69 100644
--- a/sys/winnt/win10.c
+++ b/sys/winnt/win10.c
@@ -2,7 +2,6 @@
/* Copyright (C) 2018 by Bart House */
/* NetHack may be freely redistributed. See license for details. */
-#ifdef _MSC_VER
#include "win10.h"
#include
#include
@@ -119,6 +118,3 @@ win10_is_desktop_bridge_application()
return FALSE;
}
-
-
-#endif /* _MSC_VER */
diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c
index 2a4b4f5813..14c2b1c0e3 100644
--- a/sys/winnt/windmain.c
+++ b/sys/winnt/windmain.c
@@ -474,6 +474,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
check_recordfile((char *) 0);
iflags.windowtype_deferred = TRUE;
copy_sysconf_content();
+ process_options(argc, argv);
initoptions();
/* Now that sysconf has had a chance to set the TROUBLEPREFIX, don't
@@ -481,7 +482,6 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
fqn_prefix_locked[TROUBLEPREFIX] = TRUE;
copy_config_content();
- process_options(argc, argv);
/* did something earlier flag a need to exit without starting a game? */
if (windows_startup_state > 0) {
@@ -645,19 +645,14 @@ char *argv[];
{
int i;
- /*
- * Process options.
- */
if (argc > 1) {
if (argcheck(argc, argv, ARG_VERSION) == 2)
nethack_exit(EXIT_SUCCESS);
if (argcheck(argc, argv, ARG_SHOWPATHS) == 2) {
- iflags.initoptions_noterminate = TRUE;
- initoptions();
- iflags.initoptions_noterminate = FALSE;
- reveal_paths();
- nethack_exit(EXIT_SUCCESS);
+ deferred_showpaths = TRUE;
+ /* deferred_showpaths is not used by windows */
+ return;
}
if (argcheck(argc, argv, ARG_DEBUG) == 1) {
argc--;
@@ -673,7 +668,7 @@ char *argv[];
*/
argc--;
argv++;
- const char * dir = argv[0] + 2;
+ const char *dir = argv[0] + 2;
if (*dir == '=' || *dir == ':')
dir++;
if (!*dir && argc > 1) {
@@ -740,7 +735,8 @@ char *argv[];
#endif
case 'u':
if (argv[0][2])
- (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
+ (void) strncpy(plname, argv[0] + 2,
+ sizeof(plname) - 1);
else if (argc > 1) {
argc--;
argv++;
diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c
index e7a2040a66..248a927ffb 100644
--- a/sys/winnt/winnt.c
+++ b/sys/winnt/winnt.c
@@ -45,7 +45,7 @@ boolean win32_cursorblink;
HANDLE ffhandle = (HANDLE) 0;
WIN32_FIND_DATA ffd;
extern int GUILaunched;
-boolean getreturn_enabled;
+extern boolean getreturn_enabled;
int redirect_stdout;
typedef HWND(WINAPI *GETCONSOLEWINDOW)();
diff --git a/util/.gitignore b/util/.gitignore
index 9a54f6f2e9..b5d096b0d0 100644
--- a/util/.gitignore
+++ b/util/.gitignore
@@ -11,6 +11,7 @@ lev_comp
dlb
dlb_main
recover
+stripbs
tilemap
tileedit
tile2x11
@@ -23,3 +24,6 @@ xpm2ppm.ttp
# dev tool for analyzing data collected by nethack's #define MONITOR_HEAP
heaputil
heaputil.c
+#address san
+*.exp
+*.lib
diff --git a/util/makedefs.c b/util/makedefs.c
index cd971bcc0f..5fff4f412a 100644
--- a/util/makedefs.c
+++ b/util/makedefs.c
@@ -182,7 +182,8 @@ static char *FDECL(xcrypt, (const char *));
static unsigned long FDECL(read_rumors_file,
(const char *, int *, long *, unsigned long));
static boolean FDECL(get_gitinfo, (char *, char *));
-static void FDECL(do_rnd_access_file, (const char *, const char *));
+static void FDECL(do_rnd_access_file,
+ (const char *, const char *, const char *));
static boolean FDECL(d_filter, (char *));
static boolean FDECL(h_filter, (char *));
static void NDECL(build_savebones_compat_string);
@@ -200,6 +201,7 @@ static void FDECL(do_qt_control, (char *));
static void FDECL(do_qt_text, (char *));
static void NDECL(adjust_qt_hdrs);
static void NDECL(put_qt_hdrs);
+static void FDECL(rafile, (int));
#ifdef VISION_TABLES
static void NDECL(H_close_gen);
@@ -362,22 +364,14 @@ char *options;
break;
case 's':
case 'S':
- /*
- * post-3.6.5:
- * File must not be empty to avoid divide by 0
- * in core's rn2(), so provide a default entry.
- */
- do_rnd_access_file(EPITAPHFILE,
- /* default epitaph: parody of the default engraving */
- "No matter where I went, here I am.");
- do_rnd_access_file(ENGRAVEFILE,
- /* default engraving: popularized by "The Adventures of
- Buckaroo Bonzai Across the 8th Dimenstion" but predates
- that 1984 movie; some attribute it to Confucius */
- "No matter where you go, there you are.");
- do_rnd_access_file(BOGUSMONFILE,
- /* default bogusmon: iconic monster that isn't in nethack */
- "grue");
+ rafile('1');
+ rafile('2');
+ rafile('3');
+ break;
+ case '1':
+ case '2':
+ case '3':
+ rafile(*options);
break;
case 'h':
case 'H':
@@ -420,6 +414,39 @@ const char *tag;
Unlink(name);
}
+void
+rafile(whichone)
+int whichone;
+{
+ switch(whichone) {
+ /*
+ * post-3.6.5:
+ * File must not be empty to avoid divide by 0
+ * in core's rn2(), so provide a default entry.
+ * [Second argument is used to construct a temporary file name
+ * without worrying about whether the file name macros from
+ * global.h have been modified with port-specific punctuation.]
+ */
+ case '1':
+ do_rnd_access_file(EPITAPHFILE, "epitaph",
+ /* default epitaph: parody of the default engraving */
+ "No matter where I went, here I am.");
+ break;
+ case '2':
+ do_rnd_access_file(ENGRAVEFILE, "engrave",
+ /* default engraving: popularized by "The Adventures of
+ Buckaroo Bonzai Across the 8th Dimenstion" but predates
+ that 1984 movie; some attribute it to Confucius */
+ "No matter where you go, there you are.");
+ break;
+ case '3':
+ do_rnd_access_file(BOGUSMONFILE, "bogusmon",
+ /* default bogusmon: iconic monster that isn't in nethack */
+ "grue");
+ break;
+ }
+}
+
static FILE *
getfp(template, tag, mode)
const char *template;
@@ -965,12 +992,13 @@ unsigned long old_rumor_offset;
}
static void
-do_rnd_access_file(fname, deflt_content)
-const char *fname;
+do_rnd_access_file(fname, basefname, deflt_content)
+const char *fname, *basefname;
const char *deflt_content;
{
- char *line;
+ char *line, greptmp[8 + 1 + 3 + 1];
+ Sprintf(greptmp, "grep-%.3s.tmp", basefname);
Sprintf(filename, DATA_IN_TEMPLATE, fname);
Strcat(filename, ".txt");
if (!(ifp = fopen(filename, RDTMODE))) {
@@ -993,9 +1021,9 @@ const char *deflt_content;
more likely to be picked than normal but it's nothing to worry about */
(void) fputs(xcrypt(deflt_content), ofp);
- tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE);
+ tfp = getfp(DATA_TEMPLATE, greptmp, WRTMODE);
grep0(ifp, tfp);
- ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE);
+ ifp = getfp(DATA_TEMPLATE, greptmp, RDTMODE);
while ((line = fgetline(ifp)) != 0) {
if (line[0] != '#' && line[0] != '\n')
@@ -1005,7 +1033,7 @@ const char *deflt_content;
Fclose(ifp);
Fclose(ofp);
- delete_file(DATA_TEMPLATE, "grep.tmp");
+ delete_file(DATA_TEMPLATE, greptmp);
return;
}
@@ -2273,8 +2301,9 @@ do_oracles()
void
do_dungeon()
{
- char *line;
+ char *line, greptmp[8 + 1 + 3 + 1];
+ Sprintf(greptmp, "grep-%.3s.tmp", "dun");
Sprintf(filename, DATA_IN_TEMPLATE, DGN_I_FILE);
if (!(ifp = fopen(filename, RDTMODE))) {
perror(filename);
@@ -2291,9 +2320,9 @@ do_dungeon()
}
Fprintf(ofp, "%s", Dont_Edit_Data);
- tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE);
+ tfp = getfp(DATA_TEMPLATE, greptmp, WRTMODE);
grep0(ifp, tfp);
- ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE);
+ ifp = getfp(DATA_TEMPLATE, greptmp, RDTMODE);
while ((line = fgetline(ifp)) != 0) {
SpinCursor(3);
@@ -2308,7 +2337,7 @@ do_dungeon()
Fclose(ifp);
Fclose(ofp);
- delete_file(DATA_TEMPLATE, "grep.tmp");
+ delete_file(DATA_TEMPLATE, greptmp);
return;
}
diff --git a/util/stripbs.c b/util/stripbs.c
new file mode 100644
index 0000000000..7141030e7e
--- /dev/null
+++ b/util/stripbs.c
@@ -0,0 +1,42 @@
+/* NetHack 3.6 stripbs.c */
+/* Copyright (c) Michael Allison, 2025. */
+/* NetHack may be freely redistributed. See license for details. */
+
+/*
+ * a simple filter to strip character-backspace-character
+ * from stdin and write the results to stdout.
+ */
+
+#include
+#include
+#include
+#include
+
+int main(int argc, char *argv[])
+{
+ int stop = 0, trouble = 0;
+ char buf[2];
+ char *cp = &buf[0], *prev = &buf[1];
+
+ *prev = 0;
+ while (!stop) {
+ if ((fread(buf, 1, 1, stdin)) > 0) {
+ if (*cp == 8) {
+ *prev = 0;
+ } else {
+ if (*prev)
+ fputc(*prev, stdout);
+ *prev = *cp;
+ }
+ } else {
+ if (errno != EOF)
+ trouble = 1;
+ if (*prev)
+ fputc(*prev, stdout);
+ stop = 1;
+ }
+ }
+ fflush(stdout);
+ fclose(stdout);
+ return trouble ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/win/Qt4/qt4bind.cpp b/win/Qt4/qt4bind.cpp
index 86358d1deb..5395787eca 100644
--- a/win/Qt4/qt4bind.cpp
+++ b/win/Qt4/qt4bind.cpp
@@ -455,7 +455,22 @@ int NetHackQtBind::qt_nhgetch()
// Process events until a key arrives.
//
while (keybuffer.Empty()) {
- qApp->exec();
+ int exc = qApp->exec();
+ /*
+ * On OSX (possibly elsewhere), this prevents an infinite
+ * loop repeatedly issuing the complaint:
+QCoreApplication::exec: The event loop is already running
+ * to stderr if you syncronously start nethack from a terminal
+ * then switch focus back to that terminal and type ^C.
+ * SIGINT -> done1() -> done2() -> yn_function("Really quit?")
+ * in the core asks for another keystroke.
+ *
+ * However, it still issues one such complaint, and whatever
+ * prompt wanted a response ("Really quit?") is shown in the
+ * message window but is auto-answered with ESC.
+ */
+ if (exc == -1)
+ keybuffer.Put('\033');
}
return keybuffer.GetAscii();
@@ -469,7 +484,10 @@ int NetHackQtBind::qt_nh_poskey(int *x, int *y, int *mod)
// Process events until a key or map-click arrives.
//
while (keybuffer.Empty() && clickbuffer.Empty()) {
- qApp->exec();
+ int exc = qApp->exec();
+ // [see comment above in qt_nhgetch()]
+ if (exc == -1)
+ keybuffer.Put('\033');
}
if (!keybuffer.Empty()) {
return keybuffer.GetAscii();
diff --git a/win/X11/winX.c b/win/X11/winX.c
index 463c030264..961acd21b0 100644
--- a/win/X11/winX.c
+++ b/win/X11/winX.c
@@ -82,11 +82,14 @@ static struct icon_info {
struct xwindow window_list[MAX_WINDOWS];
AppResources appResources;
void FDECL((*input_func), (Widget, XEvent *, String *, Cardinal *));
-int click_x, click_y, click_button; /* Click position on a map window */
- /* (filled by set_button_values()). */
+int click_x, click_y, click_button; /* Click position on a map window
+ * (filled by set_button_values()). */
int updated_inventory;
-static int (*old_error_handler) (Display *, XErrorEvent *);
+static void FDECL(X11_error_handler, (String)) NORETURN;
+static int FDECL(X11_io_error_handler, (Display *));
+
+static int FDECL((*old_error_handler), (Display *, XErrorEvent *));
#if !defined(NO_SIGNAL) && defined(SAFERHANGUP)
#if XtSpecificationRelease >= 6
@@ -1477,6 +1480,33 @@ XErrorEvent *error;
return 0;
}
+static void
+X11_error_handler(str)
+String str;
+{
+ nhUse(str);
+ hangup(1);
+#ifdef SAFERHANGUP /* keeps going after hangup() for '#if SAFERHANGUP' */
+ end_of_input();
+#endif
+ /*NOTREACHED*/
+ nh_terminate(EXIT_FAILURE);
+}
+
+static int
+X11_io_error_handler(display)
+Display *display;
+{
+ nhUse(display);
+ hangup(1);
+#ifdef SAFERHANGUP /* keeps going after hangup() for '#if SAFERHANGUP' */
+ end_of_input();
+#endif
+ /*NOREACHED*/ /* but not declared NORETURN */
+ return 0;
+}
+
+
void
X11_init_nhwindows(argcp, argv)
int *argcp;
@@ -1491,6 +1521,12 @@ char **argv;
for (i = 0; i < MAX_WINDOWS; i++)
window_list[i].type = NHW_NONE;
+ /* force high scores display to be shown in a window, and don't allow
+ that to be toggled off via 'O' (note: 'nethack -s' won't reach here;
+ its output goes to stdout and could be redirected into a file) */
+ iflags.toptenwin = TRUE;
+ set_option_mod_status("toptenwin", SET_IN_FILE);
+
/* add another option that can be set */
set_wc_option_mod_status(WC_TILED_MAP, SET_IN_GAME);
set_option_mod_status("mouse_support", SET_IN_GAME);
@@ -1507,7 +1543,7 @@ char **argv;
savuid = geteuid();
(void) seteuid(getuid());
- XSetIOErrorHandler((XIOErrorHandler) hangup);
+ XSetIOErrorHandler(X11_io_error_handler);
num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
@@ -2572,7 +2608,7 @@ init_standard_windows()
set_message_slider(&window_list[message_win]);
/* attempt to catch fatal X11 errors before the program quits */
- (void) XtAppSetErrorHandler(app_context, (XtErrorHandler) hangup);
+ (void) XtAppSetErrorHandler(app_context, X11_error_handler);
highlight_yn(TRUE); /* switch foreground and background */
diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c
index 1328a4828e..673ad9ba2e 100644
--- a/win/curses/cursmain.c
+++ b/win/curses/cursmain.c
@@ -45,13 +45,16 @@ struct window_procs curses_procs = {
#endif
| WC_PERM_INVENT | WC_POPUP_DIALOG | WC_SPLASH_SCREEN),
(WC2_DARKGRAY | WC2_HITPOINTBAR
+#ifdef SELECTSAVED
+ | WC2_SELECTSAVED
+#endif
#if defined(STATUS_HILITES)
| WC2_HILITE_STATUS
#endif
| WC2_FLUSH_STATUS | WC2_TERM_SIZE
| WC2_STATUSLINES | WC2_WINDOWBORDERS | WC2_PETATTR | WC2_GUICOLOR
| WC2_SUPPRESS_HIST),
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
curses_init_nhwindows,
curses_player_selection,
curses_askname,
@@ -242,6 +245,19 @@ curses_player_selection()
void
curses_askname()
{
+#ifdef SELECTSAVED
+ if (iflags.wc2_selectsaved && !iflags.renameinprogress)
+ switch (restore_menu(MAP_WIN)) {
+ case -1:
+ curses_bail("Until next time then..."); /* quit */
+ /*NOTREACHED*/
+ case 0:
+ break; /* no game chosen; start new game */
+ case 1:
+ return; /* plname[] has been set */
+ }
+#endif /* SELECTSAVED */
+
plname[0] = '\0';
curses_line_input_dialog("Who are you?", plname, PL_NSIZ);
}
diff --git a/win/curses/curswins.c b/win/curses/curswins.c
index bd2f505e8f..050549cfed 100644
--- a/win/curses/curswins.c
+++ b/win/curses/curswins.c
@@ -173,12 +173,18 @@ curses_refresh_nethack_windows()
touchwin(stdscr);
refresh();
} else {
- touchwin(status_window);
- wnoutrefresh(status_window);
- touchwin(map_window);
- wnoutrefresh(map_window);
- touchwin(message_window);
- wnoutrefresh(message_window);
+ if (status_window) {
+ touchwin(status_window);
+ wnoutrefresh(status_window);
+ }
+ if (map_window) {
+ touchwin(map_window);
+ wnoutrefresh(map_window);
+ }
+ if (message_window) {
+ touchwin(message_window);
+ wnoutrefresh(message_window);
+ }
if (inv_window) {
touchwin(inv_window);
wnoutrefresh(inv_window);
diff --git a/win/share/monsters.txt b/win/share/monsters.txt
index f2b81fc6e9..78e856adc9 100644
--- a/win/share/monsters.txt
+++ b/win/share/monsters.txt
@@ -7059,22 +7059,22 @@ Z = (195, 195, 195)
}
# tile 370 (Ixoth)
{
- ....O......O....
- ....O......O....
- ...LOOCDDCOOL...
- ...DDDDDDDDDDD..
- .CCDDDGDDGDDDCC.
- CCDKDDDDDDDDJCCC
- CDDKKKDIIDJJDCCD
- CDDKDDKJJJDDDCDD
- CCDKDDDDDDDDKCDD
- .CCDKKDDDDKKCDDD
- .CCDADKDDKDACDD.
- .DDDADDDDDDADDD.
- ....CCDDDDKKAA..
- ...CDDDAADDDKAA.
- ..CDDDAAA.DDDK..
- ................
+ ......IIIDA.....
+ .....GDGDDDA....
+ ....IDDDDDDA....
+ ..DCHHD..DDA....
+ CHCHCD..IDDA....
+ HD.D...IDDA.....
+ ......HIDAAAAAA.
+ ....IHIDAAAAAAAA
+ ..IHHIDAJDDJAAA.
+ .IHHHIDDDDDDJAA.
+ .IHHHIDDDDDDDAA.
+ DDHHIIDDDDDDDDA.
+ ID.HIDDHHDDJDJA.
+ IDAAID.AADDADDA.
+ ....IDAAJJJDDJA.
+ ........DDDDJA..
}
# tile 371 (Master Kaen)
{
diff --git a/win/win32/NetHackW.c b/win/win32/NetHackW.c
index c6941d7c05..13ec0e3108 100644
--- a/win/win32/NetHackW.c
+++ b/win/win32/NetHackW.c
@@ -15,6 +15,10 @@
#include "mhmain.h"
#include "mhmap.h"
+#if defined(__GNUC__)
+extern int mingw_main(int argc, char *argv[]);
+#endif
+
#if !defined(SAFEPROCS)
#error You must #define SAFEPROCS to build winhack.c
#endif
@@ -237,7 +241,11 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
}
GUILaunched = 1;
/* let main do the argument processing */
+#if defined(__GNUC__)
+ (void) mingw_main(argc, argv);
+#else
(void) main(argc, argv);
+#endif
return 0;
}
diff --git a/win/win32/NetHackW.rc b/win/win32/NetHackW.rc
index 7d6a88abe8..f9862f710c 100644
--- a/win/win32/NetHackW.rc
+++ b/win/win32/NetHackW.rc
@@ -320,8 +320,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,6,6,0
- PRODUCTVERSION 3,6,6,0
+ FILEVERSION 3,6,7,0
+ PRODUCTVERSION 3,6,7,0
FILEFLAGSMASK 0x1fL
#ifdef _DEBUG
FILEFLAGS 0x9L
@@ -337,13 +337,13 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "NetHack for Windows - Graphical Interface"
- VALUE "FileVersion", "3.6.6"
+ VALUE "FileVersion", "3.6.7"
VALUE "InternalName", "NetHackW"
- VALUE "LegalCopyright", "Copyright (C) 1985 - 2020. By Stichting Mathematisch Centrum and M. Stephenson. See license for details."
+ VALUE "LegalCopyright", "Copyright (C) 1985 - 2023. By Stichting Mathematisch Centrum and M. Stephenson. See license for details."
VALUE "OriginalFilename", "NetHackW.exe"
VALUE "PrivateBuild", "140606"
VALUE "ProductName", "NetHack"
- VALUE "ProductVersion", "3.6.6"
+ VALUE "ProductVersion", "3.6.7"
END
END
BLOCK "VarFileInfo"
@@ -377,17 +377,13 @@ BEGIN
END
#endif // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
+#ifdef VIA_MAKE
+#ifndef ID_MANIFEST
+#define ID_MANIFEST 1
+#endif
+#ifndef RT_MANIFEST
+#define RT_MANIFEST MAKEINTRESOURCE(24)
+#endif
+ID_MANIFEST RT_MANIFEST "NetHackW.exe.manifest"
+#endif
diff --git a/win/win32/dgnstuff.mak b/win/win32/dgnstuff.mak
index 2339a8a5a7..d32dec0ceb 100644
--- a/win/win32/dgnstuff.mak
+++ b/win/win32/dgnstuff.mak
@@ -57,7 +57,7 @@ tools:
copy $(YTABH) ..\include\dgn_comp.h
@del $(YTABC)
@del $(YTABH)
- chdir ..\build
+ chdir ..\src
!ENDIF
..\util\dgn_yacc.c : ..\util\dgn_comp.y
@@ -74,7 +74,7 @@ tools:
copy $(YTABH) ..\include\dgn_comp.h
@del $(YTABC)
@del $(YTABH)
- chdir ..\build
+ chdir ..\src
!ENDIF
..\util\dgn_lex.c: ..\util\dgn_comp.l
@@ -89,5 +89,5 @@ tools:
$(LEX) dgn_comp.l
copy $(LEXYYC) $@
@del $(LEXYYC)
- chdir ..\build
+ chdir ..\src
!ENDIF
diff --git a/win/win32/mhdlg.c b/win/win32/mhdlg.c
index cb76c9a18c..4bb33047d0 100644
--- a/win/win32/mhdlg.c
+++ b/win/win32/mhdlg.c
@@ -300,7 +300,7 @@ enum player_selector_control {
psc_control_count
};
-static const s_psc_id[psc_control_count] = {
+static const int s_psc_id[psc_control_count] = {
IDC_PLSEL_NAME_GROUP,
IDC_PLSEL_ROLE_GROUP,
IDC_PLSEL_RACE_GROUP,
@@ -574,6 +574,7 @@ plselInitDialog(struct plsel_data * data)
{
TCHAR wbuf[BUFSZ];
LVCOLUMN lvcol;
+ control_t *control;
SetWindowLongPtr(data->dialog, GWLP_USERDATA, (LONG_PTR) data);
@@ -654,10 +655,11 @@ plselInitDialog(struct plsel_data * data)
plselAdjustSelections(data->dialog);
/* set tab order */
- control_t * control = &data->controls[psc_quit_button];
- for(int i = psc_quit_button; i >= psc_name_box; i--, control++)
- SetWindowPos(control->hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
-
+ for(int i = psc_quit_button; i >= psc_name_box; i--) {
+ control = &data->controls[i];
+ SetWindowPos(control->hWnd, NULL, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE);
+ }
do_player_selector_layout(data);
center_dialog(data->dialog);
diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c
index bff7baa868..9b5e02cf47 100644
--- a/win/win32/mhmap.c
+++ b/win/win32/mhmap.c
@@ -35,8 +35,8 @@ typedef struct mswin_nethack_map_window {
int map[COLNO][ROWNO]; /* glyph map */
int bkmap[COLNO][ROWNO]; /* backround glyph map */
- boolean mapDirty[COLNO][ROWNO]; /* dirty flag for map */
-
+ boolean locDirty[COLNO][ROWNO]; /* dirty flag for map location */
+ boolean mapDirty; /* one or more map locations are dirty */
int mapMode; /* current map mode */
boolean bAsciiMode; /* switch ASCII/tiled mode */
boolean bFitToScreenMode; /* switch Fit map to screen mode on/off */
@@ -141,7 +141,7 @@ mswin_init_map_window()
}
void
-mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw)
+mswin_map_layout(HWND hWnd, LPSIZE map_size)
{
/* check arguments */
if (!IsWindow(hWnd) || !map_size || map_size->cx <= 0
@@ -364,10 +364,11 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw)
mswin_cliparound(data->xCur, data->yCur);
- if (redraw) {
- dirtyAll(data);
- InvalidateRect(hWnd, NULL, TRUE);
- }
+ // redraw all map locations
+ dirtyAll(data);
+
+ // invalidate entire map window
+ InvalidateRect(hWnd, NULL, TRUE);
}
/* set map mode */
@@ -475,13 +476,38 @@ mswin_map_mode(HWND hWnd, int mode)
mapSize.cx = data->tileWidth * COLNO;
mapSize.cy = data->tileHeight * ROWNO;
- mswin_map_stretch(hWnd, &mapSize, TRUE);
+ mswin_map_layout(hWnd, &mapSize);
mswin_update_inventory(); /* for perm_invent to hide/show tiles */
return oldMode;
}
+void mswin_map_update(HWND hWnd)
+{
+ PNHMapWindow data = (PNHMapWindow)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+ if (data->mapDirty)
+ {
+ /* update back buffer */
+ HBITMAP savedBitmap = SelectObject(data->tileDC, GetNHApp()->bmpMapTiles);
+
+ for (int i = 0; i < COLNO; i++)
+ for (int j = 0; j < ROWNO; j++)
+ if (data->locDirty[i][j])
+ {
+ paint(data, i, j);
+ RECT rect;
+ nhcoord2display(data, i, j, &rect);
+ InvalidateRect(data->hWnd, &rect, FALSE);
+ }
+
+ SelectObject(data->tileDC, savedBitmap);
+ data->mapDirty = FALSE;
+ }
+
+}
+
/* register window class for map window */
void
register_map_window_class()
@@ -553,7 +579,7 @@ MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
size.cx = data->xFrontTile * COLNO;
size.cy = data->yFrontTile * ROWNO;
}
- mswin_map_stretch(hWnd, &size, TRUE);
+ mswin_map_layout(hWnd, &size);
/* update window placement */
GetWindowRect(hWnd, &rt);
@@ -971,11 +997,8 @@ static void setGlyph(PNHMapWindow data, int i, int j, int fg, int bg)
if ((data->map[i][j] != fg) || (data->bkmap[i][j] != bg)) {
data->map[i][j] = fg;
data->bkmap[i][j] = bg;
- data->mapDirty[i][j] = TRUE;
-
- RECT rect;
- nhcoord2display(data, i, j, &rect);
- InvalidateRect(data->hWnd, &rect, FALSE);
+ data->locDirty[i][j] = TRUE;
+ data->mapDirty = TRUE;
}
}
@@ -985,28 +1008,23 @@ static void clearAll(PNHMapWindow data)
for (int y = 0; y < ROWNO; y++) {
data->map[x][y] = NO_GLYPH;
data->bkmap[x][y] = NO_GLYPH;
- data->mapDirty[x][y] = TRUE;
+ data->locDirty[x][y] = TRUE;
}
- InvalidateRect(data->hWnd, NULL, FALSE);
+ data->mapDirty = TRUE;
}
static void dirtyAll(PNHMapWindow data)
{
for (int i = 0; i < COLNO; i++)
for (int j = 0; j < ROWNO; j++)
- data->mapDirty[i][j] = TRUE;
-
- InvalidateRect(data->hWnd, NULL, FALSE);
+ data->locDirty[i][j] = TRUE;
+ data->mapDirty = TRUE;
}
static void dirty(PNHMapWindow data, int x, int y)
{
- data->mapDirty[x][y] = TRUE;
-
- RECT rt;
- nhcoord2display(data, data->xCur, data->yCur, &rt);
-
- InvalidateRect(data->hWnd, &rt, FALSE);
+ data->locDirty[x][y] = TRUE;
+ data->mapDirty = TRUE;
}
static void
@@ -1025,7 +1043,7 @@ paint(PNHMapWindow data, int i, int j)
paintTile(data, i, j, &rect);
}
- data->mapDirty[i][j] = FALSE;
+ data->locDirty[i][j] = FALSE;
}
@@ -1035,16 +1053,6 @@ onPaint(HWND hWnd)
{
PNHMapWindow data = (PNHMapWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
- /* update back buffer */
- HBITMAP savedBitmap = SelectObject(data->tileDC, GetNHApp()->bmpMapTiles);
-
- for (int i = 0; i < COLNO; i++)
- for (int j = 0; j < ROWNO; j++)
- if (data->mapDirty[i][j])
- paint(data, i, j);
-
- SelectObject(data->tileDC, savedBitmap);
-
PAINTSTRUCT ps;
HDC hFrontBufferDC = BeginPaint(hWnd, &ps);
diff --git a/win/win32/mhmap.h b/win/win32/mhmap.h
index 695749431d..d6e6c7d1dd 100644
--- a/win/win32/mhmap.h
+++ b/win/win32/mhmap.h
@@ -11,8 +11,9 @@
COLORREF nhcolor_to_RGB(int c);
HWND mswin_init_map_window(void);
-void mswin_map_stretch(HWND hWnd, LPSIZE lpsz, BOOL redraw);
+void mswin_map_layout(HWND hWnd, LPSIZE lpsz);
int mswin_map_mode(HWND hWnd, int mode);
+void mswin_map_update(HWND hWnd);
#define ROGUE_LEVEL_MAP_MODE MAP_MODE_ASCII12x16
#define ROGUE_LEVEL_MAP_MODE_FIT_TO_SCREEN MAP_MODE_ASCII_FIT_TO_SCREEN
diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c
index 62e78480f1..5e6884c5b9 100644
--- a/win/win32/mhmenu.c
+++ b/win/win32/mhmenu.c
@@ -950,14 +950,18 @@ onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
/* Set the height of the list box items to max height of the individual
* items */
for (i = 0; i < data->menu.size; i++) {
+/* int map_y = GetNHApp()->mapTile_Y; */
+ int map_y = 16; /* leave it at the default size, unless
+ * we are actually showing the larger
+ * icons in the menu */
if (NHMENU_HAS_GLYPH(data->menu.items[i])
&& !IS_MAP_ASCII(iflags.wc_map_mode)) {
lpmis->itemHeight =
max(lpmis->itemHeight,
- (UINT) max(tm.tmHeight, GetNHApp()->mapTile_Y) + 2);
+ (UINT) max(tm.tmHeight, map_y) + 2);
} else {
lpmis->itemHeight =
- max(lpmis->itemHeight, (UINT) max(tm.tmHeight, TILE_Y) + 2);
+ max(lpmis->itemHeight, (UINT) max(tm.tmHeight, map_y) + 2);
}
}
diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c
index a7e4fd8878..e542927283 100644
--- a/win/win32/mswproc.c
+++ b/win/win32/mswproc.c
@@ -1835,6 +1835,7 @@ void
mswin_delay_output()
{
logDebug("mswin_delay_output()\n");
+ mswin_map_update(mswin_hwnd_from_winid(WIN_MAP));
Sleep(50);
}
@@ -2103,9 +2104,11 @@ mswin_putmsghistory(const char *msg, BOOLEAN_P restoring)
void
mswin_main_loop()
{
- MSG msg;
-
while (!mswin_have_input()) {
+ MSG msg;
+
+ mswin_map_update(mswin_hwnd_from_winid(WIN_MAP));
+
if (!iflags.debug_fuzzer || PeekMessage(&msg, NULL, 0, 0, FALSE)) {
if(GetMessage(&msg, NULL, 0, 0) != 0) {
if (GetNHApp()->regNetHackMode
@@ -2197,7 +2200,7 @@ initMapTiles(void)
map_size.cx = GetNHApp()->mapTile_X * COLNO;
map_size.cy = GetNHApp()->mapTile_Y * ROWNO;
- mswin_map_stretch(mswin_hwnd_from_winid(WIN_MAP), &map_size, TRUE);
+ mswin_map_layout(mswin_hwnd_from_winid(WIN_MAP), &map_size);
return TRUE;
}
diff --git a/win/win32/nethack.rc b/win/win32/nethack.rc
index cea237a21a..95e8d0cdb6 100644
--- a/win/win32/nethack.rc
+++ b/win/win32/nethack.rc
@@ -60,8 +60,8 @@ IDI_ICON1 ICON "nethack.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,6,6,0
- PRODUCTVERSION 3,6,6,0
+ FILEVERSION 3,6,7,0
+ PRODUCTVERSION 3,6,7,0
FILEFLAGSMASK 0x1fL
#ifdef _DEBUG
FILEFLAGS 0x9L
@@ -77,12 +77,12 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "NetHack for Windows - TTY Interface"
- VALUE "FileVersion", "3.6.6"
+ VALUE "FileVersion", "3.6.7"
VALUE "InternalName", "NetHack"
- VALUE "LegalCopyright", "Copyright (C) 1985 - 2020. By Stichting Mathematisch Centrum and M. Stephenson. See license for details."
+ VALUE "LegalCopyright", "Copyright (C) 1985 - 2023. By Stichting Mathematisch Centrum and M. Stephenson. See license for details."
VALUE "OriginalFilename", "NetHack.exe"
VALUE "ProductName", "NetHack"
- VALUE "ProductVersion", "3.6.6"
+ VALUE "ProductVersion", "3.6.7"
END
END
BLOCK "VarFileInfo"
diff --git a/win/win32/vs2017/NetHack.sln b/win/win32/vs2017/NetHack.sln
index 0d5df6b896..aa2bb75622 100644
--- a/win/win32/vs2017/NetHack.sln
+++ b/win/win32/vs2017/NetHack.sln
@@ -54,29 +54,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uudecode", "uudecode.vcxpro
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHack", "NetHack.vcxproj", "{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}"
ProjectSection(ProjectDependencies) = postProject
+ {93F10526-209E-41D7-BBEA-775787876895} = {93F10526-209E-41D7-BBEA-775787876895}
{63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB}
{9DD9C52E-E8C9-4533-BD22-83C055C0AABA} = {9DD9C52E-E8C9-4533-BD22-83C055C0AABA}
{BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}
- {6813477F-64B6-4B97-B230-438D0D233385} = {6813477F-64B6-4B97-B230-438D0D233385}
{0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC}
{8A3F81C7-2968-49A8-86BF-2669412AD7DE} = {8A3F81C7-2968-49A8-86BF-2669412AD7DE}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhdefkey", "nhdefkey.vcxproj", "{6813477F-64B6-4B97-B230-438D0D233385}"
- ProjectSection(ProjectDependencies) = postProject
- {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nh340key", "nh340key.vcxproj", "{BE04E242-A1E9-4593-B95B-057F37330B76}"
- ProjectSection(ProjectDependencies) = postProject
- {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhraykey", "nhraykey.vcxproj", "{2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}"
- ProjectSection(ProjectDependencies) = postProject
- {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945}
- EndProjectSection
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDCurses", "PDCurses.vcxproj", "{BAA70D0F-3EC7-4D10-91F0-974F1F49308B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{477BF231-48E0-4312-AA12-9D8576215489}"
@@ -174,30 +159,6 @@ Global
{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.Build.0 = Release|Win32
{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.ActiveCfg = Release|x64
{609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.Build.0 = Release|x64
- {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.ActiveCfg = Debug|Win32
- {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.Build.0 = Debug|Win32
- {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.ActiveCfg = Debug|x64
- {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.Build.0 = Debug|x64
- {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.ActiveCfg = Release|Win32
- {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.Build.0 = Release|Win32
- {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.ActiveCfg = Release|x64
- {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.Build.0 = Release|x64
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.ActiveCfg = Debug|Win32
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.Build.0 = Debug|Win32
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.ActiveCfg = Debug|x64
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.Build.0 = Debug|x64
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.ActiveCfg = Release|Win32
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.Build.0 = Release|Win32
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.ActiveCfg = Release|x64
- {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.Build.0 = Release|x64
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.ActiveCfg = Debug|Win32
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.Build.0 = Debug|Win32
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.ActiveCfg = Debug|x64
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.Build.0 = Debug|x64
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.ActiveCfg = Release|Win32
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.Build.0 = Release|Win32
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.ActiveCfg = Release|x64
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.Build.0 = Release|x64
{BAA70D0F-3EC7-4D10-91F0-974F1F49308B}.Debug|Win32.ActiveCfg = Debug|Win32
{BAA70D0F-3EC7-4D10-91F0-974F1F49308B}.Debug|Win32.Build.0 = Debug|Win32
{BAA70D0F-3EC7-4D10-91F0-974F1F49308B}.Debug|x64.ActiveCfg = Debug|x64
diff --git a/win/win32/vs2017/NetHackPackage.appxmanifest b/win/win32/vs2017/NetHackPackage.appxmanifest
index 12b8d3ad19..c97a4fff16 100644
--- a/win/win32/vs2017/NetHackPackage.appxmanifest
+++ b/win/win32/vs2017/NetHackPackage.appxmanifest
@@ -1,6 +1,6 @@
-
+ NetHack 3.6NetHack DevTeam
diff --git a/win/win32/vs2017/NetHackProperties.props b/win/win32/vs2017/NetHackProperties.props
index b95cec9614..f9c3ea4e8f 100644
--- a/win/win32/vs2017/NetHackProperties.props
+++ b/win/win32/vs2017/NetHackProperties.props
@@ -4,7 +4,7 @@
36
- 6
+ 7
diff --git a/win/win32/vs2017/nh340key.def b/win/win32/vs2017/nh340key.def
deleted file mode 100644
index f484a536fb..0000000000
--- a/win/win32/vs2017/nh340key.def
+++ /dev/null
@@ -1,8 +0,0 @@
-LIBRARY nh340key
-EXPORTS
-ProcessKeystroke
-NHkbhit
-CheckInput
-SourceWhere
-SourceAuthor
-KeyHandlerName
diff --git a/win/win32/vs2017/nh340key.vcxproj b/win/win32/vs2017/nh340key.vcxproj
deleted file mode 100644
index 36278a8a36..0000000000
--- a/win/win32/vs2017/nh340key.vcxproj
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
- {BE04E242-A1E9-4593-B95B-057F37330B76}
- Win32Proj
- nh340key
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(BinDir)
-
-
-
- $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)
-
-
- $(ToolsDir)$(TargetName).lib
-
-
-
-
- nh340key.def
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/win/win32/vs2017/nhdefkey.def b/win/win32/vs2017/nhdefkey.def
deleted file mode 100644
index 2950904e4c..0000000000
--- a/win/win32/vs2017/nhdefkey.def
+++ /dev/null
@@ -1,8 +0,0 @@
-LIBRARY nhdefkey
-EXPORTS
-ProcessKeystroke
-NHkbhit
-CheckInput
-SourceWhere
-SourceAuthor
-KeyHandlerName
diff --git a/win/win32/vs2017/nhdefkey.vcxproj b/win/win32/vs2017/nhdefkey.vcxproj
deleted file mode 100644
index 71334f591f..0000000000
--- a/win/win32/vs2017/nhdefkey.vcxproj
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
- {6813477F-64B6-4B97-B230-438D0D233385}
- Win32Proj
- nhdefkey
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(BinDir)
-
-
-
- $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)
-
-
- $(ToolsDir)$(TargetName).lib
-
-
-
-
- nhdefkey.def
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/win/win32/vs2017/nhraykey.def b/win/win32/vs2017/nhraykey.def
deleted file mode 100644
index 5432a1af35..0000000000
--- a/win/win32/vs2017/nhraykey.def
+++ /dev/null
@@ -1,8 +0,0 @@
-LIBRARY nhraykey
-EXPORTS
-ProcessKeystroke
-NHkbhit
-CheckInput
-SourceWhere
-SourceAuthor
-KeyHandlerName
diff --git a/win/win32/vs2017/nhraykey.vcxproj b/win/win32/vs2017/nhraykey.vcxproj
deleted file mode 100644
index 5e0e43b2df..0000000000
--- a/win/win32/vs2017/nhraykey.vcxproj
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
- {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}
- Win32Proj
- nhraykey
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(BinDir)
-
-
-
- $(IncDir);$(SysWinntDir);%(AdditionalIncludeDirectories)
-
-
- $(ToolsDir)$(TargetName).lib
-
-
-
-
- nhraykey.def
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/win/win32/vs2017/travisci.sh b/win/win32/vs2017/travisci.sh
index 812f4cdd85..f9fd227b6e 100644
--- a/win/win32/vs2017/travisci.sh
+++ b/win/win32/vs2017/travisci.sh
@@ -13,6 +13,7 @@ export PATH=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/$VSVER/$TOOLSVE
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 PATH=$PATH:/c/ProgramData/chocolatey/lib/winflexbison/tools
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
@@ -27,8 +28,13 @@ export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/10/lib/$WKITVER/um/x86:$LIB
git clone --depth 1 https://github.com/wmcbrine/PDCurses.git ../pdcurses
export ADD_CURSES=Y
export PDCURSES_TOP=../../pdcurses
-export
+export YACC="win_bison -y"
+export LEX=win_flex.exe
+export YTABC=y.tab.c
+export YTABH=y.tab.h
+export LEXYYC=lex.yy.cexport
cd src
+mkdir ../binary
cp ../sys/winnt/Makefile.msc ./Makefile
nmake install
cd ..